2013-01-18 26 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怎麼辦?

您可以優化一個因素。在你做之前,你必須確保它是正確的,最重要的是你必須記住這是一臺真正的機器。你擁有的資源是有限的,所以優化總是會剝奪彼得支付保羅的費用。彼得可能會生氣......