在 C# 中读取非常大的文本文件的最快方法

Fastest way to read very large text file in C#

我有一个非常基本的问题。我有几个文本文件,每个文件的数据大小为几 GB。我有一个 C# WPF 应用程序,我用它来处理类似的数据文件,但远不及那个大小(现在可能大约 200-300mb)。我怎样才能有效地读取这些数据,然后在处理后将它写到别处,而不至于所有东西都冻结和崩溃?从本质上讲,从一个非常大的文件中读取的最佳方法是什么?对于我现在的小规模应用程序,我使用 System.IO.File.ReadAllLines 读取和 streamwriter 写入。我确信这两种方法对于如此大的文件来说不是最好的主意。我对 C# 没有太多经验,任何帮助将不胜感激!

如果您可以逐行执行此操作,那么答案很简单:

  1. 读一行。
  2. 处理行。
  3. 写下这行。

如果你想让它走得快一点,把它们放在三个 BlockingCollections 中,并指定一个上限,比如 10,这样一个较慢的步骤永远不会等待更快的步骤。如果可以输出到不同的物理光盘(如果输出到光盘)。

即使在被问及该过程是否逐行(两次)后,OP 仍更改了规则。

  1. 读取行以生成工作单元(从打开到关闭标签)。
  2. 处理工作单元。
  3. 写工作单元。

这可能是某种重叠转换。

https://msdn.microsoft.com/en-us/library/dd997372(v=vs.110).aspx

首先,您需要将目标文件分配为尽可能接近可估计的结果大小。在大多数情况下,超调可能比欠调更可取,您始终可以截断到给定长度,但增长可能需要非连续分配。如果预期过度增长,您可以将文件分配为 "sparse" 文件。

选择大于或等于 512 字节的任意(可能是二进制幂)块大小(测试以找到最佳性能)。

映射源文件的2个块。这是您的源缓冲区。

映射目标文件的 2 个块。这是您的目标缓冲区。

对块内的行进行操作。从源块读取,写入目标块。

转换块边界后,执行 "buffer swap" 将前一个完成的块换成下一个块。

有几种方法可以完成这些任务。

如果您愿意,您可以一次为操作分配更多块,但您需要应用 "triple buffering" 重叠操作策略才能使用。如果写入比读取慢得多,您甚至可以使用与三重缓冲相同的模式实现无限内存缓冲。

根据您的数据,您还可以将块分发到单独的线程,即使它是一个 "line based" 文件。

如果每一行都依赖于之前的数据,可能没有办法加速运行。如果不是,在执行操作之前索引文件中的行将允许多个工作线程,每个工作线程在独立的块上运行。

如果我需要详细说明什么,就说哪一部分。