C#读取大文件上的字节模式

时间:2016-04-15 02:57:42

标签: c# file design-patterns byte

我是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;
    }
}

我仍在测试我的代码,现在我意识到我的代码在开始时不符合模式时会变得冻结,或者在开始和满足模式之间存在很大的差距。是否有任何改进我的代码的建议,以便在开始和第一个匹配模式之间存在较大差距时不会冻结。谢谢

1 个答案:

答案 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;
}