在C#中处理大文件

7

我有一个4GB的文件,想要进行基于字节的查找和替换。我写了一个简单的程序来实现它,但是执行一个查找和替换需要太长时间(超过90分钟),而一些我尝试过的十六进制编辑器可以在不将整个目标文件加载到内存中的情况下在3分钟以内完成任务。是否有人知道我可以实现相同功能的方法?以下是我的当前代码:

    public int ReplaceBytes(string File, byte[] Find, byte[] Replace)
    {
        var Stream = new FileStream(File, FileMode.Open, FileAccess.ReadWrite);
        int FindPoint = 0;
        int Results = 0;
        for (long i = 0; i < Stream.Length; i++)
        {
            if (Find[FindPoint] == Stream.ReadByte())
            {
                FindPoint++;
                if (FindPoint > Find.Length - 1)
                {
                    Results++;
                    FindPoint = 0;
                    Stream.Seek(-Find.Length, SeekOrigin.Current);
                    Stream.Write(Replace, 0, Replace.Length);
                }
            }
            else
            {
                FindPoint = 0;
            }
        }
        Stream.Close();
        return Results;
    }

顺便说一下,“查找和替换”与那个4GB的“文件”相比较小。我很容易看出我的算法为什么慢,但我不确定如何改进。


8
首先,一次读取超过1个字节的内容。 - SLaks
http://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_algorithm - SLaks
5个回答

3

问题的一部分可能是因为您一次只读取一个字节流。尝试读取较大的块并对其进行替换。我建议从大约8kb开始,然后测试一些更大或更小的块,以查看哪个能给您最好的性能。


3
有很多更好的算法用于在字符串中查找子字符串(这基本上就是您要做的事情)。从这里开始:http://en.wikipedia.org/wiki/String_searching_algorithm。它们的要点是,通过分析子字符串,可以跳过许多字节。以下是一个简单的例子:

4GB文件以以下方式开头:A B C D E F G H I J K L M N O P

您的子字符串是:N O P

  1. 跳过子字符串长度减1个字节并检查最后一个字节,因此将C与P进行比较
  2. 它不匹配,因此子字符串不是前3个字节
  3. 而且,C根本不在子字符串中,因此可以跳过3个字节(子字符串的长度)
  4. 将F与P进行比较,不匹配,F不在子字符串中,跳过3个字节
  5. 将I与P进行比较,等等
如果匹配,则向后移动。如果字符不匹配但在子字符串中,则必须在该点上进行一些比较(请阅读链接了解详情)。

2

不要逐字节读取文件,而是通过缓冲区进行读取:

buffer = new byte[bufferSize];            
currentPos = 0;
length = (int)Stream .Length;
while ((count = Stream.Read(buffer, currentPos, bufferSize)) > 0)
{
   currentPos += count;
   ....
}

1

另一种更简单的一次读取多个字节的方法:

var Stream = new BufferedStream(new FileStream(File, FileMode.Open, FileAccess.ReadWrite));

结合Saeed Amiri的缓冲读取示例和更好的二进制查找/替换算法,应该能够给您带来更好的结果。

1

你应该尝试使用内存映射文件。C#从4.0版本开始支持它们。

内存映射文件包含虚拟内存中文件的内容。

持久化文件是与磁盘上源文件相关联的内存映射文件。当最后一个进程完成对文件的操作后,数据将保存到磁盘上的源文件中。这些内存映射文件适用于处理极大的源文件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接