我正在寻找一些关于如何解码和读取 zstd 文件的建议,我感觉有点失落,因为这是我开始学习 Rust 以来的第一个大项目。
我在这个项目中使用 Rust,因为它是为了实习,并且数据导出/压缩工具是很久以前用 Rust 编写的,所以我想我可以得到一些灵感。我正在从头开始学习 Rust,所以我对文件 i/o 过程的结构和功能不是很熟悉。我有一个代码片段当前无法工作,所以我有一些问题:
use std::fs::File;
use std::io::{self, BufReader};
use zstd::stream::read::Decoder;
fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
where P: AsRef<Path>, {
if let Ok(file) = File::open(filename) {
if let Ok(buf_reader) = BufReader::new(file) {
if let Ok(decoder) = Decoder::new(buf_reader) {
return Ok(io::BufReader::new(decoder).lines()); } } } }
if let Ok(lines) = read_lines(filename) {
for line in lines {
if let Ok(ip) = line {
println!("{}", ip)
}
}
}
既然是压缩文件,是不是应该先整体解码,然后再逐行读取呢?我知道解压后的文件是 jsonl 格式,所以每一行都是一个单独的 json 文件。如果文件太大无法一次性读取,我该怎么办?
另外,如果您正在使用的 zstd 之外还有其他推荐的软件包,请与我分享。我将不胜感激所有的帮助。
您正在以正确的方式进行操作,在
Decoder
中使用 BufReader
将允许您从压缩文件中读取行,而不需要预先加载整个文件。用于读取行的外部BufReader
将从解码器读取块,直到到达换行符,并且从解码器读取将从文件中解码块。
您只是结构和返回类型不正确。这就是我要做的:
use std::fs::File;
use std::io::{BufRead, BufReader, Error as IoError, Lines};
use std::path::Path;
use zstd::stream::read::Decoder;
fn read_lines<P>(filename: P) -> Result<Lines<BufReader<Decoder<'static, BufReader<File>>>>, IoError>
where
P: AsRef<Path>,
{
let file = File::open(filename)?;
let decoder = Decoder::new(file)?;
Ok(BufReader::new(decoder).lines())
}
再解释一下:
File::open
和Decoder::new
都会返回std::io::Error
,如果遇到问题,我们可以使用?
提前返回错误并避免嵌套if-let
。Decoder::new
接受阅读器类型并创建 Decoder<'_, BufReader<_>>
(即,它为 BufReader
本身创建 File
),因此我们不必执行该部分。Result<Lines<impl BufRead>, IoError>
以保持简洁。