因此,我试图对大于可用 RAM 的 gz 压缩文件执行某种面向行的操作,因此排除首先将其读入字符串的情况。问题是,如何在 Rust 中做到这一点(缺少gunzip file.gz|./my-rust-program)?
我当前的解决方案基于flate2一堆缓冲读取器:
use std::path::Path;
use std::io::prelude::*;
use std::io::BufReader;
use std::fs::File;
use flate2::bufread::GzDecoder as BufGzDecoder;
fn main() {
let mut fname = "path_to_a_big_file.gz";
let f = File::open(fname).expect("Ooops.");
let bf = BufReader::new(f); // Here's the first reader so I can plug data into BufGzDecoder.
let br = BufGzDecoder::new(bf); // Yep, here. But, oops, BufGzDecoder has not lines method,
// so try to stick it into a std BufReader.
let bf2 = BufReader::new(br); // What!? This works!? Yes it does.
// After a long time ...
eprintln!("count: {}",bf2.lines().count());
// ... the line count is here.
}
Run Code Online (Sandbox Code Playgroud)
简而言之,我注意到我无法将文件直接插入到 中flate2::bufread::GzDecoder,因此我首先创建了std::io::BufReader与前者的构造函数方法兼容的实例。但是,我没有看到与 相关的任何有用的迭代器flate2::bufread::GzDecoder,因此我std::io::BufReader在其之上构建了另一个迭代器。令人惊讶的是,这有效,我得到了我的Lines迭代器,它在我的机器上用了不到一分钟的时间读取了整个文件,但感觉它过于冗长和不优雅,而且可能效率低下(更担心这部分)。
E_n*_*ate 10
问题中描述的每个“缓冲诱导”步骤在这里都是必要的。
BufReader将用于识别行分隔模式并准确返回完整的文本行。然而,第一个有一个捷径。该flate2板条箱提供了read::GzDecoder,它需要一个常规读取器并自动在其上使用缓冲读取。
use flate2::read::GzDecoder;
let reader = BufReader::new(GzDecoder::new(file));
Run Code Online (Sandbox Code Playgroud)
完成此操作后,推荐的提高效率的方法是确保程序是使用正确的配置文件(释放read_line模式)构建的,并通过使用而不是迭代器为每一行重用相同的 String 值lines(),从而减少内存分配的次数。
也可以看看:
| 归档时间: |
|
| 查看次数: |
2528 次 |
| 最近记录: |