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

本文关键字:大型 文本 文件 3-5GB 修改 读取 | 更新日期: 2023-09-27 18:25:02

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

我曾厚颜无耻地尝试过File.ReadAllLines,但没有成功。然后,我试着将以下行流式传输,从原始文件中读取并写入新文件。当它完成这项工作时,它会在几个小时内完成(5+)。我读过关于使用缓冲区的文章,这听起来是唯一的选择,但我该如何保持线路的完整性?

解决方案:StreamWriter移动到while的外部。使用count而不是拆分。

 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();
          }
       }
    }
}

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

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

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

斯普利特(";")也可能对速度产生影响,但我认为影响不大。无论如何,字符串操作应该在C#中小心进行,因为字符串是免疫的,可能会在内存中创建大量垃圾。因此,如果您可以检查4个分号,那么它总是比调用Split(';')要好,后者分配一个数组,并(在您的情况下)在内存中每行创建5个字符串。当使用不可变字符串执行大量字符串操作时,即使没有任何磁盘I/O,也可能严重影响应用程序性能。

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