读取和修改大文本文件3-5GB

时间:2013-07-25 08:59:44

标签: c# filestream streamreader streamwriter file-handling

我有一个相当大的文件,包含数百万行,需要检查并删除文件中的损坏行。

我无耻地试过File.ReadAllLines,但它没有用。然后我尝试在原始文件中读取以下行并写入新文件。虽然它可以完成这项工作,但它可以在几个小时内完成(5+)。我已经阅读过有关使用缓冲区的内容,这听起来像是唯一的选择,但我如何以这种方式保持线路完整性?

解决方案: StreamWriter移动到了while之外。使用count而不是split。

 using (FileStream inputStream = File.OpenRead((localFileToProcess + ".txt")))
 {
    using (StreamReader inputReader = new StreamReader(inputStream, System.Text.Encoding.GetEncoding(1254)))
    {
       using(StreamWriter writer=new StreamWriter(localFileToProcess,true,System.Text.Encoding.GetEncoding(1254)))
       {
          while (!inputReader.EndOfStream)
          {
             if ((tempLineValue = inputReader.ReadLine()).Count(c => c == ';') == 4)
             {
                 writer.WriteLine(tempLineValue);
             }
             else
                 incrementCounter();
          }
       }
    }
}

1 个答案:

答案 0 :(得分:1)

我认为原始代码中最慢的部分是创建/处理StreamWriter。在每个Dispose上,StreamWriter必须将所有未写入的数据刷新到光盘,关闭文件句柄等。在开放式操作系统上必须检查安全权限,当前锁定还要执行许多其他操作。

当您开始只使用一个StreamWriter时,其内部写缓冲区开始以大块的形式将数据写入磁盘。除了跳过关闭/打开文件以进行写入之外,还可以节省大量时间。磁盘I / O通常是应用程序中最慢的部分。

分裂(';')也有可能影响速度,但我认为它不太重要。无论如何,字符串操作应该在C#中小心地完成,因为字符串是不可变的,并且可以在内存中创建大量垃圾。因此,如果你可以检查4个分号,那么总是比调用Split(';')更好,它会分配一个数组,并且(在你的情况下)每行在内存中创建5个字符串。当使用不可变字符串执行大量字符串操作时,即使没有任何光盘I / O,它也可能会严重影响应用程序性能。

至于在你的情况下使用StringBuilder - 我不认为它有多大帮助,因为StreamWriter已经内置了缓冲。