0

假设我有一个 1 GB 的文本文件,我想阅读它。如果我尝试打开此文件,我会收到“内存溢出”错误。我知道,通常的答案是“使用 StreamReader.ReadLine() 方法”。但我想知道这是如何工作的。如果使用 ReadLine 方法的程序想要获取一行,它迟早要打开整个文本文件。据我所知,文件存储在磁盘上,可以按照“全有或全无”的原则在内存中打开它们。如果使用 ReadLine() 方法一次只将我的 1 GB 文本文件的一行存储在内存中,这意味着我们必须在读取 1 GB 文本文件的每一行时为它进行磁盘 IO。这对性能来说不是一件可怕的事情吗?

我很困惑,我想要一些关于这个的细节。

4

3 回答 3

5

这意味着我们必须为我的 1 GB 文本文件的每一行磁盘 IO

不,您的 ReadLine() 调用和物理磁盘之间有很多层,旨在不造成问题。最重要的是:

  • FileStream 是为 StreamReader 执行工作的基础类,它使用缓冲区来减少 ReadFile() 调用的数量。默认大小为 4096 字节
  • ReadFile() 从文件系统缓存而不是磁盘读取文件数据。这可能会导致调用磁盘驱动程序,但这并不常见。操作系统足够聪明,可以猜测您可能会从文件中读取更多数据并从磁盘中预读取数据,只要这样做成本低且 RAM 不用于其他任何用途。它通常会消耗整个磁盘柱面的数据。
  • 磁盘驱动器本身也有一个缓存,通常是几兆字节。

文件系统缓存是迄今为止最重要的一个。这也是一个棘手的问题,因为它会阻止您准确地分析您的程序。当您一遍又一遍地运行测试时,您的程序实际上从不从磁盘读取,而只是从缓存中读取。这使它变得不切实际地快。尽管 1 GB 的文件可能不太适合,但取决于您的机器中有多少 RAM。

于 2013-01-18T22:57:00.327 回答
1

通常在幕后FileStream打开一个对象,该对象从磁盘读取文件的大块并将其拉入内存。该块充当cacheReadLine() 的读取对象,因此您不必担心每个 ReadLine() 都会导致磁盘访问。

于 2013-01-18T22:48:59.210 回答
0

可怕的事情是为了表现什么?

显然它应该更快,因为您有可用的内存来处理内存中的整个文件。

但是,查找和分配一个连续的块是有代价的。

演出是一个重要的内存块,如果你的进程有它,有什么伤害?

交换比流媒体更容易受到伤害。

您是否一次需要所有文件,您是否一直需要它?

如果你去读/写。那会对你有什么影响?

如果文件转到 2 gig 怎么办?

您可以针对一个因素进行优化。在你这样做之前,你必须确保它是正确的,最重要的是你必须记住这是一台真正的机器。你的资源是有限的,所以优化总是让彼得付钱给保罗。彼得可能会生气...

于 2013-01-18T22:58:54.167 回答