2013-01-18 27 views
0

比方说,我有一个1 GB的文本文件,我想阅读它。如果我试图打开这个文件,我会得到一个“内存溢出”的错误。我知道,通常的答案是“使用StreamReader.ReadLine()方法”。但我想知道这是如何工作的。如果使用ReadLine方法的程序想要获取一行,它将不得不早晚打开整个文本文件。据我所知,文件存储在磁盘上,它们可以用“全部或全部”原则在内存中打开。如果通过使用ReadLine()方法一次只将我的1 GB文本文件的一行存储在内存中,这意味着我们必须在读取1GB文本文件的每一行时为I-O磁盘。对于表演来说这不是一件可怕的事情吗?ReadLine如何在.NET中工作

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

+1

仅供参考,'ReadLine'不是C#的一部分 - 它是.NET的一部分。 –

回答

5

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

没有,有很多你的ReadLine()调用和物理磁盘,设计成不间层使这成为一个问题。最要紧的那些:

  • 的FileStream,底层的类,它针对的StreamReader工作,采用了缓冲,以减少ReadFile的数量()调用。默认大小是4096字节
  • ReadFile()从文件系统缓存中读取文件数据,而不是从磁盘读取文件数据。 可能导致对磁盘驱动程序的调用,但这并不常见。操作系统是足够聪明的猜测,你很可能会从文件中读取和数据从磁盘,只要是便宜做和RAM不被用于其他任何预读它。它通常会吞噬整个磁盘柱面的数据。
  • 磁盘驱动器本身也有缓存,通常是几兆字节。

文件系统缓存是迄今为止最重要的一个。这也是一个棘手的问题,因为它会阻止你准确地分析你的程序。当你反复运行你的测试时,你的程序其实从来没有从磁盘读取,只有缓存。这使得它不现实的速度很快。虽然1 GB文件可能不太合适,但取决于您在机器中拥有多少RAM。

1

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

0

可怕的事情是什么表现?

显然,这应该会更快,因为你必须具备处理内存中的整个文件的存储。

查找并分配一个连续块是一个成本虽然。

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

交换实现很容易伤人,更流。

你所需要的所有文件一次,你需要这一切的时候?

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

如果文件去2 gig怎么办?

您可以优化一个因素。在你做之前,你必须确保它是正确的,最重要的是你必须记住这是一台真正的机器。你拥有的资源是有限的,所以优化总是会剥夺彼得支付保罗的费用。彼得可能会生气......