在C#中处理大量文件

我有一个4Gb文件,我想执行基于字节的查找和替换。 我已经编写了一个简单的程序来完成它,但是只需要一个查找和替换就需要太长时间(90分钟+)。 我尝试过的一些hex编辑器可以在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  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“文件”相比,查找和替换相对较小。 我很容易理解为什么我的算法很慢但我不确定如何才能做得更好。

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

有很多更好的算法可以在字符串中查找子字符串(这基本上就是你在做什么)

从这里开始:

http://en.wikipedia.org/wiki/String_searching_algorithm

它们的要点是通过分析子字符串可以跳过很多字节。 这是一个简单的例子

4GB文件以:ABCDEFGHIJKLMNOP开头

你的子串是:NOP

  1. 跳过substring-1的长度并检查最后一个字节,因此将C与P进行比较
  2. 它不匹配,因此子字符串不是前3个字节
  3. 此外,C根本不在子字符串中,因此您可以跳过3个字节(子字符串的len)
  4. 将F与P进行比较,不匹配,F不在子字符串中,跳过3
  5. 比较我和P等等

如果匹配,请向后退。 如果字符不匹配,但是在子字符串中,那么你必须在那一点做更多的比较(阅读链接了解详情)

而不是逐字节读取文件,而不是缓冲区读取它:

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

另一种更容易的方法是一次读取多个字节:

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

将此与Saeed Amiri的如何读入缓冲区的示例相结合,以及更好的二进制查找/替换算法之一应该可以为您提供更好的结果。

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

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

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