Rust : décompresser en flux un fichier JSONlines compressé en XZ et afficher un attribut unique
Ce programme d’exemple analyse un fichier JSONlines compressé en XZ et affiche l’attribut timestamp de chaque ligne s’il est présent. Les lignes invalides ou vides sont ignorées.
main.rs
stream_decompress.rs
//! Ce programme lit en flux et décompresse un fichier JSONlines compressé en XZ,
//! analyse chaque ligne comme du JSON, et affiche le champ "timestamp" s'il est présent.
//! Les lignes invalides ou vides sont ignorées.
use std::fs::File; // Pour ouvrir le fichier
use std::io::{BufRead, BufReader}; // Pour la lecture bufferisée
use anyhow::{Context, Result}; // Pour la gestion des erreurs
use serde::Deserialize; // Pour désérialiser le JSON
use xz2::read::XzDecoder; // Pour la décompression XZ
/// Représente une ligne unique dans le fichier JSONlines.
/// Seul le champ "timestamp" est extrait.
#[derive(Deserialize, Debug)]
struct Line {
timestamp: Option<f64>,
}
/// Traite le fichier JSONlines compressé en XZ donné.
/// Le décompresse à la volée, analyse chaque ligne comme du JSON,
/// et affiche l'horodatage s'il est disponible. Ignore les lignes invalides.
fn process_file(path: &str) -> Result<()> {
// Ouvrir le fichier
let file = File::open(path).with_context(|| format!("Échec de l'ouverture du fichier : {}", path))?;
// Créer un lecteur bufferisé pour l'efficacité
let reader = BufReader::new(file);
// Envelopper avec le décompresseur XZ
let decompressor = XzDecoder::new(reader);
// Un autre lecteur bufferisé pour la lecture ligne par ligne
let buf_reader = BufReader::new(decompressor);
// Itérer sur chaque ligne
for line_result in buf_reader.lines() {
let line = match line_result {
Ok(l) => l,
Err(_) => continue, // Ignorer les lignes avec des erreurs d'E/S
};
// Ignorer les lignes vides
if line.trim().is_empty() {
continue;
}
// Essayer d'analyser comme du JSON
match serde_json::from_str::<Line>(&line) {
Ok(obj) => {
// Afficher l'horodatage s'il est présent
if let Some(ts) = obj.timestamp {
println!("{}", ts);
}
}
Err(e) => {
eprintln!("Échec de l'analyse de la ligne JSON : {}", e);
continue;
}
}
}
Ok(())
}
/// Point d'entrée principal.
/// Prend le chemin du fichier comme premier argument, ou utilise le fichier d'exemple par défaut.
fn main() -> Result<()> {
// Exiger le chemin du fichier comme premier argument positionnel.
// S'il manque, afficher un court message d'utilisation et sortir avec un code non nul.
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!("Utilisation : {} <chemin-vers-fichier-jsonlines-xz>", prog);
std::process::exit(2);
}
};
// Traiter le fichier
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"Exemple d’entrée
example.json
{"timestamp": 1744267290.991, "status": "ok"}
{"timestamp": 1744267291.987, "status": "ok"}
{"status": "missing timestamp"}
invalid json lineNotez que vous devez compresser ce fichier avec XZ pour créer le fichier d’entrée du programme.
compress_example.sh
xz example.jsonCompilation et exécution
run_decompress_example.sh
cargo run -- example.json.xzSortie attendue :
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