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

本文关键字:文本 文件 方法 读取 非常 | 更新日期: 2023-09-27 17:56:29

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

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

如果你可以逐行做到这一点,那么答案很简单:

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

如果您希望它走得更快一点,请将它们放在三个BlockingCollections中,指定的上限为 10,这样较慢的步骤永远不会等待更快的步骤。 如果可以输出到其他物理光盘(如果输出到光盘)。

OP甚至在被问及该过程是否逐行(两次)后也更改了规则。

  1. 读取行以生成工作单元(从打开到关闭标记)。
  2. 进程工作单元。
  3. 写入工作单元。

这可能是某种重叠的转换。

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

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

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

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

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

在块内的线路上操作。从源块读取,写入目标块。

转换区块边界后,执行"缓冲区交换"以将上一个完成的区块换取下一个区块。

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

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

根据您的数据,您还可以将块分发到单独的线程,即使它是"基于行"的文件。

如果每行都依赖于以前的数据,则可能无法加速操作。否则,在执行操作之前为文件中的行编制索引将允许多个工作线程,每个工作线程在独立的块上运行。

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