gpt4 book ai didi

c# - 如何将大量数据写入文件?

转载 作者:太空狗 更新时间:2023-10-29 23:56:37 30 4
gpt4 key购买 nike

我正在开发一个应用程序,它从巨大的文本文件 (~2.5 GB) 中读取行,将每一行处理为特定格式,然后将每一行写入一个文本文件。关闭输出文本文件后,程序“批量插入”(SQL Server) 数据到我的数据库中。它有效,只是速度慢。

我正在使用 StreamReaderStreamWriter

由于我必须如何操作文本,我几乎只能一次阅读一行;但是,我认为如果我制作一个行集合并每 1000 行左右写出这个集合,它至少会加快速度。问题是(这可能完全是我的无知)我无法使用 StreamWriter 编写 string[]。在探索了 StackOverflow 和互联网的其余部分之后,我遇到了 File.WriteAllLines,它允许我将 string[] 写入文件,但我不认为我的计算机内存可以处理一次存储的 2.5 GB 数据。此外,该文件已创建、填充和关闭,因此我必须制作大量较小的文件来分解 2 GB 的文本文件,以便将它们插入数据库。所以我宁愿远离那个选项。

我能想到的一个 hack 工作是制作一个 StringBuilder 并使用 AppendLine 方法添加每一行以制作一个巨大的字符串。然后我可以将该 StringBuilder 转换为字符串并将其写入文件。

但我的猜测已经够多了。我已经实现的方法有效,但我想知道是否有人可以建议更好的方法将数据 block 写入文件?

最佳答案

使用 StreamWriter 有两件事可以提高输出速度。

首先,确保输出文件与输入文件位于不同的物理磁盘上。如果输入和输出在同一个驱动器上,那么经常读取必须等待写入而写入必须等待读取。磁盘一次只能做一件事。显然不是每次读取或写入都等待,因为StreamReader 读入缓冲区并解析其中的行,而StreamWriter 写入缓冲区然后在缓冲区已满时将其推送到磁盘。由于输入和输出文件位于不同的驱动器上,您的读取和写入会重叠。

它们重叠是什么意思?操作系统通常会为您预读,因此它可以在您处理文件时缓冲您的文件。当您进行写入时,操作系统通常会对其进行缓冲并将其延迟写入磁盘。因此,正在进行一些有限数量的异步处理。

第二件事是增加缓冲区大小。 StreamReaderStreamWriter 的默认缓冲区大小为 4 KB。因此,每读取或写入 4K 都会引发一次操作系统调用。而且,很可能是磁盘操作。

如果将缓冲区大小增加到 64K,那么操作系统调用将减少 16 倍,磁盘操作将减少 16 倍(严格来说并非如此,但接近)。使用 64K 缓冲区可以减少超过 25% 的 I/O 时间,而且非常简单:

const int BufferSize = 64 * 1024;
var reader = new StreamReader(filename, Encoding.UTF8, true, BufferSize);
var writer = new StreamWriter(filename, Encoding.UTF8, BufferSize);

这两件事比您可以做的任何其他事情都更能加快您的 I/O 速度。尝试使用 StringBuilder 在内存中构建缓冲区只是不必要的工作,它无法复制通过增加缓冲区大小可以实现的目标,而且做得不正确很容易使您的程序变慢.

我会警告缓冲区大小不要超过 64 KB。在某些系统上,使用高达 256 KB 的缓冲区,您会获得略微更好的结果,但在其他系统上,您会获得非常糟糕的性能——慢 50%!我从未看到一个系统在缓冲区大于 256 KB 时比在缓冲区 64 KB 时性能更好。根据我的经验,64 KB 是最佳选择。

您可以做的另一件事是使用三个线程:读取器、处理器和写入器。他们与队列通信。这可以将您的总时间从 (input-time + process-time + output-time) 减少到非常接近 max(input-time, process-time, output-time)。使用 .NET,它的设置真的很容易。查看我的博文:Simple multithreading, Part 1Simple multithreading, Part 2 .

关于c# - 如何将大量数据写入文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17870296/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com