FileStream.Seek与缓冲读取

时间:2010-12-06 17:43:24

标签: c# file-io

this answer的动机我想知道如果使用大量的FileStream.Seek(-1),幕后会发生什么。

为清楚起见,我会重新发布答案:

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个字节读入缓冲区并在该缓冲区中搜索char。

使用Reflector我发现内部方法正在使用SetFilePointer

是否有关于Windows缓存和向后读取文件的文档? Windows是否“向后”缓冲并在使用连续Seek(-1)时查询缓冲区,还是从当前位置开始提前读取?

有趣的是,一方面大多数人都同意Windows进行良好的缓存,但另一方面,“向后读取文件”的每个答案都涉及读取字节块并在该块上运行。

2 个答案:

答案 0 :(得分:6)

前进与后退并不会产生太大的影响。在第一次读取后,文件数据被读入文件系统缓存,您将在ReadByte()上获得内存到内存的副本。只要数据在缓存中,该副本对文件指针值不敏感。然而,缓存算法确实可以假设您通常按顺序读取。只要文件扇区仍然在同一轨道上,它就会尝试提前读取。它们通常是,除非磁盘严重碎片化。

但是,是效率低下的。每个字节都有两个pinvoke和API调用。这有相当多的开销,相同的两个调用也可以读取,例如65千字节,具有相同的开销。像往常一样,只有当你发现它是一个性能瓶颈时才解决这个问题。

答案 1 :(得分:1)

这是File Caching in Windows

上的指针

行为还可能取决于物理驻留文件的位置(硬盘,网络等)以及本地配置/优化。

另一个重要的信息来源是CreateFile API文档:CreateFile Function

有一个名为“缓存行为”的好部分至少告诉我们如何影响文件缓存,至少在非托管世界中是这样。