我是C#的新手,我想在文件中计算一个字节模式。当我尝试读取一个小文件(8MB)并获得1907结果时,一切都很好,但是当我尝试读取一个大文件(50MB)时,应用程序冻结并且什么也没有返回。到目前为止,这是我的代码。
public long chunkMethodCW()
{
int incomingOffset = 0;
byte[] outboundBuffer = new byte[1024];
long CW = 0;
KMP kmp = new KMP(header); // header = pattern in hex
while(incomingOffset < data.Length)
{
int length = Math.Min(outboundBuffer.Length,data.Length - incomingOffset);
Buffer.BlockCopy(data,incomingOffset,outboundBuffer,0,length);
incomingOffset += length;
//CW += kmp.match(outboundBuffer);
CW++;
}
return CW;
}
// KMP Class
public class KMP
{
private int[] F;
private byte[] pat;
private int m;
public KMP(byte[] pattern)
{
pat = pattern;
m = pattern.Length;
F = new int[m + 1];
for (int i = 2, j; i <= m; i++)
{
j = F[i - 1];
if (pattern[j] == pattern[i - 1])
{
F[i] = j + i;
continue;
}
while(j > 0 && pat[j] != pat[i-1])
{
j = F[j];
}
F[i] = pat[j] != pat[i - 1] ? 0 : j + 1;
}
}
public int match(byte[] data)
{
int n = data.Length, pi = 0, ti = 0;
int matches = 0;
while (ti < n)
{
if (pi == m)
{
matches++;
pi = 0;
pi = F[pi];
}
if (data[ti] == pat[pi])
{
pi++;
ti++;
}
else if (pi > 0)
{
pi = F[pi];
}
else
{
ti++;
}
}
if (pi == m)
{
matches++;
pi = 0;
pi = F[pi];
}
return matches;
}
}
我仍在测试我的代码,现在我意识到我的代码在开始时不符合模式时会变得冻结,或者在开始和满足模式之间存在很大的差距。是否有任何改进我的代码的建议,以便在开始和第一个匹配模式之间存在较大差距时不会冻结。谢谢
答案 0 :(得分:0)
您能提供以下信息:您的源和模式字节数组长度是多少?我试过,它没有给我任何冻结文件63MB。
哦,顺便说一句,我发现了一个&#34; bug&#34;在你的实施中。它应该使用某种&#34;窗口&#34; 1024字节长吧?基本上,字节被复制到窗口,KMP将模式匹配应用于窗口,窗口滑动到读取下一个字节。因此,如果截止值位于模式的中间,则不会返回正确数量的模式匹配。我已经更正了下面的代码,因此窗口每次都会减少(为了考虑可能的&#34; cut&#34;模式):
public static long SearchBytePattern(byte[] source, byte[] patternToFind)
{
int incomingOffset = 0;
byte[] window = new byte[1024];
long count = 0;
KMP kmp = new KMP(patternToFind);
while (incomingOffset < source.Length)
{
int length = Math.Min(window.Length, source.Length - incomingOffset);
Buffer.BlockCopy(source, incomingOffset, window, 0, length);
incomingOffset += length;
count += kmp.match(window);
if (incomingOffset >= source.Length)
break;
else
incomingOffset -= patternToFind.Length - 1;
}
return count;
}