我的应用程序使用一个非常大的文件,并在一个小窗口内从各种偏移量执行许多非常小的读取.我将直接文件读取替换为通过BufReader读取.然后我用进程监视器(来自Sysinterals套件)判断了操作系统执行的实际读取操作,似乎根本没有缓冲任何内容.更糟糕的是,它现在每次都读取整个缓冲区容量,这使得性能变得更差.

播放:

use std::fs::File;
use std::io::{BufReader, Read, Seek, SeekFrom};

fn main() {
    let path = "data.bin";
    let f = File::open(path).unwrap();
    let mut r = BufReader::with_capacity(8 * 1024, f);

    let mut buf = [0; 8];

    r.seek(SeekFrom::Start(0)).unwrap();
    r.read(&mut buf).unwrap();

    r.seek(SeekFrom::Start(100)).unwrap();
    r.read(&mut buf).unwrap();

    r.seek(SeekFrom::Start(200)).unwrap();
    r.read(&mut buf).unwrap();
}

在这种情况下,我应该如何使用BufReader

推荐答案

这是通过实施Seek::seek for BufReader来实现的:

查找到基础读取器中的偏移量(以字节为单位).

用来寻找SeekFrom::Current(_)的位置是 基础读取器的位置(如果BufReader<R>没有 内部缓冲区.

寻道始终丢弃内部缓冲区,即使寻道位置 否则就会落在这个范围内.这保证了呼叫 BufReader::into_inner()在搜索之后立即产生潜在的 读卡器在同一位置.

要在不丢弃内部缓冲区的情况下进行查找,请使用 BufReader::seek_relative.

有关更多详细信息,请参见std::io::Seek.

注意:在边缘情况下,您正在寻找SeekFrom::Current(n) 其中,n减go 内部缓冲区长度溢出i64,两次查找 将被执行而不是一次.如果第二次查找返回错误,则 基础读取器将保留在与以下情况相同的位置 你用SeekFrom::Current(0)呼叫了Seek.

推理已列出,并提供了针对您的用例的变通方法...具体来说,请拨打BufReader::seek_relative:

相对于当前位置进行搜索.如果新位置位于缓冲区内,则不会刷新缓冲区,从而允许更高效的查找.此方法不返回基础读取器的位置,因此调用方必须自己跟踪此信息(如果需要).

Rust相关问答推荐

为什么在Rust struct 中只允许最后一个字段具有动态大小的类型

在‘await’点上使用‘std::同步::Mutex’是否总是会导致僵局?

什么是Rust惯用的方式来使特征向量具有单个向量项的别名?

如何模拟/创建ReqData以测试Actix Web请求处理程序?

告诉Rust编译器返回值不包含构造函数中提供的引用

如何修复&q;无法返回引用函数参数的值在异步规则中返回引用当前函数&q;拥有的数据的值?

考虑到Rust不允许多个可变引用,类似PyTorch的自动区分如何在Rust中工作?

在 Rust 中,在需要引用 self 的 struct 体方法中使用闭包作为 while 循环条件

Rust 如何返回大类型(优化前)?

相当于 Rust 中 C++ 的 std::istringstream

将多维数组转换为切片

如何基于常量在Rust中跳过一个测试

在多核嵌入式 Rust 中,我可以使用静态 mut 进行单向数据共享吗?

使用 lalrpop 在 rust 中解析由 " 引用的字符串

当 T 不是副本时,为什么取消引用 Box 不会抱怨移出共享引用?

Rust 将特性传递给依赖项

为什么具有 Vec 变体的枚举没有内存开销?

没有分号的返回表达式的性能是否比使用返回更好?在Rust ?

Rust 跨同一文件夹中文件的可见性

有没有比多个 push_str() 调用更好的方法将字符串链接在一起?