2010-12-06 86 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

有一个名为“缓存行为”的好节告诉我们,至少你如何能够影响的文件缓存,在不可控制的世界,至少。