在文件中搜索字节序列(C#)

时间:2010-11-25 16:01:19

标签: c# algorithm file-io pattern-matching

我正在编写一个C#应用程序,我需要在其中搜索一个字节序列的文件(可能非常大),我不能使用任何库来执行此操作。所以,我需要一个函数,它将一个字节数组作为参数,并返回给定序列后面的字节位置。该功能不一定非常快,只需要工作即可。任何帮助将不胜感激:)

3 个答案:

答案 0 :(得分:3)

如果它不是很快,你可以使用它:

int GetPositionAfterMatch(byte[] data, byte[]pattern)
{
  for (int i = 0; i < data.Length - pattern.Length; i++)
  {
    bool match = true;
    for (int k = 0; k < pattern.Length; k++)
    {
      if (data[i + k] != pattern[k])
      {
        match = false;
        break;
      }
    }
    if (match)
    {
      return i + pattern.Length;
    }
  }
}

但我真的建议你使用Knuth-Morris-Pratt算法,它的算法主要用作字符串的IndexOf方法的基础。上面的算法执行速度非常慢,适用于小数组和小模式。

答案 1 :(得分:1)

Turrau指出的直接方法很有用,并且就你的目的而言可能已经足够好了,因为你说它不必很快 - 特别是因为对于大多数实际来说,算法比最差的要快得多案例O(n * m)。 (根据你的模式,我猜)。

对于最佳解决方案,您还可以查看Knuth-Morris-Pratt algorithm,它使用部分匹配,最后是O(n + m)。

答案 2 :(得分:1)

这是我用来进行boyer-moore类型搜索的一些代码的摘录。它的意思是处理pcap文件,所以它按记录操作,但应该很容易修改,以适应只搜索一个长的二进制文件。它是从一些测试代码中提取的,所以我希望我能为你提供一切。还要查看维基百科上的boyer-moore搜索,因为这是它的基础。

int[] badMatch = new int[256];
byte[] pattern;  //the pattern we are searching for

//badMath is an array of every possible byte value (defined as static later).
//we use this as a jump table to know how many characters we can skip comparison on
//so first, we prefill every possibility with the length of our search string
for (int i = 0; i < badMatch.Length; i++)
{
  badMatch[i] = pattern.Length;
}

//Now we need to calculate the individual maximum jump length for each byte that appears in my search string
for (int i = 0; i < pattern.Length - 1; i++)
{
  badMatch[pattern[i] & 0xff] = pattern.Length - i - 1;
}

// Place the bytes you want to run the search against in the payload variable
byte[] payload = <bytes>

// search the packet starting at offset, and try to match the last character
// if we loop, we increment by whatever our jump value is
for (i = offset + pattern.Length - 1; i < end && cont; i += badMatch[payload[i] & 0xff])
{
  // if our payload character equals our search string character, continue matching counting backwards
  for (j = pattern.Length - 1, k = i; (j >= 0) && (payload[k] == pattern[j]) && cont; j--)
  {
    k--;
  }
// if we matched every character, then we have a match, add it to the packet list, and exit the search (cont = false)
  if (j == -1)
  {
    //we MATCHED!!!
    //i = end;
    cont = false;
  }
}