2010-12-06 78 views
5

動力this answer我想知道如果使用大量的FileStream.Seek(-1),幕下會發生什麼。FileStream.Seek與緩衝讀取

爲清楚起見,我會重新發布了答案:

using (var fs = File.OpenRead(filePath)) 
{ 
    fs.Seek(0, SeekOrigin.End); 

    int newLines = 0; 
    while (newLines < 3) 
    { 
     fs.Seek(-1, SeekOrigin.Current); 
     newLines += fs.ReadByte() == 13 ? 1 : 0; // look for \r 
     fs.Seek(-1, SeekOrigin.Current); 
    } 

    byte[] data = new byte[fs.Length - fs.Position]; 
    fs.Read(data, 0, data.Length); 
} 

個人而言,我會像讀2048個字節到緩衝區和搜索的字符該緩衝區。

使用反射器我發現內部方法是使用SetFilePointer

是否有任何關於Windows緩存和向後讀文件的文檔? Windows緩衝「向後」並在連續使用Seek(-1)時諮詢緩衝區,還是從當前位置開始預讀?

有趣的是,一方面大多數人都贊同Windows做好緩存,但另一方面,「向後讀取文件」的每個答案都涉及讀取字節塊並在該塊上進行操作。

+1

做一些認真的同行評審吧? – ChaosPandion 2010-12-06 20:05:53

+0

@ChaosPandion:我沒有評價你的評論,我只是好奇。 – VVS 2010-12-06 21:26:55

回答

6

前進vs後退通常沒有太大的區別。在第一次讀取之後,文件數據被讀入文件系統緩存中,您將在ReadByte()上獲得內存到內存的副本。只要數據在緩存中,該副本對文件指針值不敏感。然而,緩存算法的工作原理是你通常會順序讀取的。它試圖提前閱讀,只要文件扇區仍在同一軌道上。通常情況下,除非磁盤碎片太多。

但是,這是低效的。對於每個單獨的字節,您將得到兩次pinvoke和API調用。這裏有相當多的開銷,那些相同的兩個調用也可以讀取,例如65千字節,具有相同的開銷。像往常一樣,只有當你發現它是一個性能瓶頸時才解決這個問題。

1

這裏是關於File Caching in Windows

行爲可能也取決於其中物理上駐留的文件(硬盤,網絡等),以及本地配置/優化的指針。

的也是重要的信息來源是的CreateFile API文檔:CreateFile Function

有一個名爲「緩存行爲」的好節告訴我們,至少你如何能夠影響的文件緩存,在不可控制的世界,至少。