c# - 如何修复我的方法为较小的数组扫描大量字节

时间:2017-09-10 13:56:32

标签: c# arrays byte

我想创建一种方法来扫描特定数组的字节数组 我已经完成了这个,但我还想要其他东西,我想扩展它 因此它可以通过用256(0xff)替换它们来扫描一些索引是未知的数组 例如 如果我有这样的数组[1,2,3,4,5,6,7,8,9,20,30,50] 通常情况下,我可以搜索[5,6,7],它会索引[4]因为那是5开始的地方 我希望能够搜索[5,256,7]之类的东西,这意味着如果我不知道 256的实际值,我仍然会得到正确的答案

我的解决方案是抓取一个256/512字节的块,使用for循环读取一个x字节的块(在这种情况下,3个字节),并用字节中相应索引的相应值替换256读

这是我试过的代码,但它无法正常工作

p.s,这个方法是为了扫描真正大的数组,这就是为什么有一些大的值

public long arraySearch(byte[] scanFor, long startIndex, long endIndex)
{
    if (scanFor.Length == 0 || startIndex == 0 || endIndex == 0 || endIndex 
<= startIndex - scanFor.Length) return 0;

    long tempStart = startAddress;
    long foundIndex = 0;
    long tmpAd = 0;

    long maxChunk = endIndex - startIndex;
    float parts = maxChunk / 256;

    int x = 0;
    byte[] tmp = new byte[scanFor.Length];
    byte[] buf = new byte[256];

    for (x = 0; x < parts; x++) 
    {
//the 'byte[] ReadArray(int64 index,int length)' method returns a byte array 
(byte[]) at the given index of the specified size
        buf = ReadArray(tempStart, 256);

        for (int i = 0; i < 256; i++)
        {

            if (buf[i] == scanFor[0])
            {
                tmp = ReadArray(tempStart + i, scanFor.Length);
                    for (int iii = 0; iii < scanFor.Length; iii++)
                    {
                        if (scanFor[iii] == 0xff) scanFor[iii] = tmp[iii];
                    }

                tmpAd = tempStart + i;
//the 'ByteArrayCompare' method compares all elements of an array and 
returns true if all are equal
                if (ByteArrayCompare(tmp, scanFor))
                {
                    foundIndex = tmpAd;
                    break;
                }
            }
        }
        tempStart += 256;
    }
    return foundIndex;
}

1 个答案:

答案 0 :(得分:0)

我觉得你的代码非常令人困惑,所以我无法告诉你它的错误,但我可以试着用你的尝试为你解释一个有效的解决方案。

首先,我创建了一些帮助程序来模拟你的环境 - 告诉我,我是否理解了错误(这些部分只是为了简化我的事情):

private static readonly byte [] FirstPart = Enumerable.Repeat (1, 250).Select (i => (byte) i).ToArray ();
private static readonly byte [] SecondPart = Enumerable.Range (1, 250).Select (i => (byte) i).ToArray ();
private static readonly byte [] ThirdPart = Enumerable.Range (0, 250).Select (i => (byte) i).ToArray ();
private static readonly byte [] FourthPart = Enumerable.Repeat (1, 500).Select (i => (byte) i).ToArray ();

private static readonly byte [] WholeArray =
    new [] {FirstPart, SecondPart, ThirdPart, FourthPart}.SelectMany (bytes => bytes).ToArray ();

private static byte [] ReadArray (long index, int length) =>
    WholeArray.Where ((b, i) => i >= index && i < index + length).ToArray ();

然后这就是我提出的ArraySearch的实现 - 我在评论中解释过,如果有什么不清楚的地方,请随时问:

public static long ArraySearch (byte [] scanFor, long startIndex, long endIndex)
{
    if (startIndex < 0 ||
        endIndex < startIndex ||
        scanFor.Length > endIndex - startIndex) //Check wether the parameters are valid
        return -1;

    if (scanFor.Length == 0) //If the scanFor is empty, we must return 0 directly, 
        //as an IndexOutOfRange exception would be caused otherwise
        return 0;

    var partsCount = (endIndex - startIndex) / 256; //The number of parts to scan

    long tempFoundIndex = -1; //The found index, that is later going to be returned

    for (var i = 0; i < partsCount; i++) //We iterate through the parts 
        //to find an item in those parts which matches the first item of the array we're searching for
    {
        var start = i * 256 + startIndex; //This is the startIndex of the current part
        if (start > endIndex) //If the start index is already bigger than the endIndex, we can directly break, 
            //because we won't find the array in the specified range anymore 
            break;
        var part = ReadArray (start, 256); //This is the part we're currently scanning

        for (var j = 0; j < part.Length && start + j <= endIndex; j++) //Now we're iterating this part
            //to find the item which matches the first item of the array we're searching for
            if (scanFor [0] == 0xFF || part [j] == scanFor [0]) //If we found such an item, 
                //we want to check all following items, wether they match the to search array as well
            {
                var arrayCheckFailed = false; //This indicates wether it already failed, 
                //so that it doesn't continue to search
                var tempScanForIndex = 0; //This is the index of the item from ScanFor we're currently checking
                tempFoundIndex = start + j; //This is the starting index we found 
                //and we later want to return, if all items match
                for (var i2 = i; i2 < partsCount && !arrayCheckFailed; i2++) 
                    //So we're once again iterating through the parts (beginning from the current part)
                    //to check the items from the parts
                {
                    var start2 = i2 * 256 + startIndex; //This is once again the startIndex of the current part
                    if (start2 > endIndex) //see above
                        break;
                    var part2 = ReadArray (start2, 256);//TODO RENAME
                    for (var j2 = i2 == i ? j : 0; j2 < part2.Length && start2 + j2 <= endIndex; j2++)
                        if (scanFor [tempScanForIndex] == 0xFF || part2 [j2] == scanFor [tempScanForIndex])
                        {
                            tempScanForIndex++; //If the current item matched, we want to check the next item
                            if (scanFor.Length <= tempScanForIndex) //And if we checked enough items, 
                                //we know that the array matches, so we can return the found index
                                return tempFoundIndex;
                        }
                        else
                        {
                            arrayCheckFailed = true; 
                                //If it didn't match we continue to search for a first item which matches
                            tempFoundIndex = -1; 
                            break;
                        }
                }
            }
    }
    return tempFoundIndex;
}

我用这种方法测试了这个:

private static void Main ()
{
    Console.Write (ArraySearch (ThirdPart.Select ((b, i) => i == 0 ? (byte) 0xFF : b).ToArray (), 0, 1100));
    Console.ReadLine ();
}

输出为249,这对我来说是正确的。

我无法在您的环境中对其进行测试,因此,如果某些内容无法正常工作,请通知我。