FileStream.Seek与缓冲读取

VVS*_*VVS 5 c# file-io

这个答案的推动下,我想知道如果一个人使用了很多东西,幕后会发生什么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);
}
Run Code Online (Sandbox Code Playgroud)

就个人而言,我会将2048个字节读入缓冲区并在该缓冲区中搜索char.

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

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

有趣的是,一方面大多数人都同意Windows进行良好的缓存,但另一方面,"向后读取文件"的每个答案都涉及读取字节块并对该块进行操作.

Han*_*ant 6

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

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