c# - FileStream.Seek 与缓冲读取

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

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

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

有趣的是,一方面大多数人同意 Windows 做的好的缓存,但另一方面每个对“向后读取文件”的回答都涉及读取字节 block 并对该 block 进行操作。

最佳答案

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

但是,是的,它是低效的。对于每个单独的字节,您会遇到两次 pinvoke 和 API 调用。这其中有相当多的开销,同样的两个调用也可以读取,比如说,65 KB 的开销相同。与往常一样,仅当您发现它是性能瓶颈时才修复它。

关于c# - FileStream.Seek 与缓冲读取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4369278/

相关文章:

c# - flickr oauth 签名无效错误

c# - Lambda Func<> 和 Fluent

php - Codeigniter 多个文件上传困惑文件扩展名

c - 使用 fread 将数据存储到 char 缓冲区中

android - C 文件 open() 函数仅在 Android 中设置用户级别权限

c# - 自定义 OWIN CookieAuthenticationProvider 在第一次/冷启动时失败

c# - 标识方法的开始和结束

c# - 我如何让 resharper 为我构建一个基于当前字段或类中 Prop 的简单流畅的界面

windows - 如何从 Perl 中的任意文件类型读取数据?

mysql - 在存储过程中使用 LOAD DATA INFILE 命令