Rust 示例:流式解压 xz 压缩的 JSONL 文件并打印单个属性
此示例程序解析 xz 压缩的 JSONL 文件,并在存在时打印每一行的 timestamp 属性。无效或空行将被忽略。
main.rs
stream_decompress.rs
//! 本程序流式读取并解压用 xz 压缩的 JSONL 文件,
//! 将每一行解析为 JSON,并在存在时打印 "timestamp" 字段。
//! 无效或空行将被忽略。
use std::fs::File; // 用于打开文件
use std::io::{BufRead, BufReader}; // 用于缓冲读取
use anyhow::{Context, Result}; // 用于错误处理
use serde::Deserialize; // 用于反序列化 JSON
use xz2::read::XzDecoder; // 用于 xz 解压
/// 表示 JSONL 文件中的单行。
/// 仅提取 "timestamp" 字段。
#[derive(Deserialize, Debug)]
struct Line {
timestamp: Option<f64>,
}
/// 处理给定的 xz 压缩 JSONL 文件。
/// 实时解压,将每一行解析为 JSON,
/// 并在可用时打印时间戳。忽略无效行。
fn process_file(path: &str) -> Result<()> {
// 打开文件
let file = File::open(path).with_context(|| format!("打开文件失败:{}", path))?;
// 创建缓冲读取器以提高效率
let reader = BufReader::new(file);
// 用 xz 解压器包装
let decompressor = XzDecoder::new(reader);
// 再创建一个缓冲读取器用于逐行读取
let buf_reader = BufReader::new(decompressor);
// 遍历每一行
for line_result in buf_reader.lines() {
let line = match line_result {
Ok(l) => l,
Err(_) => continue, // 跳过有 IO 错误的行
};
// 跳过空行
if line.trim().is_empty() {
continue;
}
// 尝试解析为 JSON
match serde_json::from_str::<Line>(&line) {
Ok(obj) => {
// 如果存在则打印时间戳
if let Some(ts) = obj.timestamp {
println!("{}", ts);
}
}
Err(e) => {
eprintln!("解析 JSON 行失败:{}", e);
continue;
}
}
}
Ok(())
}
/// 主入口点。
/// 将文件路径作为第一个参数,如果未提供则使用默认示例文件。
fn main() -> Result<()> {
// 要求文件路径作为第一个位置参数。
// 如果缺失,打印简短用法信息并以非零退出码退出。
let mut args = std::env::args();
let prog = args.next().unwrap_or_else(|| "rust_parse_status_logs".to_string());
let path = match args.next() {
Some(p) => p,
None => {
eprintln!("用法:{} <path-to-xz-jsonlines-file>", prog);
std::process::exit(2);
}
};
// 处理文件
process_file(&path)
}Cargo.toml
Cargo.toml
[package]
name = "rust_parse_status_logs"
version = "0.1.0"
edition = "2021"
[dependencies]
serde = { version = "1", features = ["derive"] }
serde_json = "1"
xz2 = "0.1"
anyhow = "1"示例输入
example.json
{"timestamp": 1744267290.991, "status": "ok"}
{"timestamp": 1744267291.987, "status": "ok"}
{"status": "missing timestamp"}
invalid json line请注意,你需要用 xz 压缩此文件才能创建程序的输入文件。
compress_example.sh
xz example.json构建与运行
run_decompress_example.sh
cargo run -- example.json.xz预期输出:
decompress_output.txt
Finished dev [unoptimized + debuginfo] target(s) in 0.05s
Running `target/debug/rust_parse_status_logs example.json.xz`
1744267290.991
1744267291.987
Failed to parse JSON line: expected value at line 1 column 1Check out similar posts by category:
Rust
If this post helped you, please consider buying me a coffee or donating via PayPal to support research & publishing of new posts on TechOverflow