Я использую bsdtar для передачи содержимого файла .tar.gz
, содержащего множество (миллионов) xml-файлов, на стандартный вывод.
В настоящее время я использую команду:
$ bsdtar -x -f <file.tar.gz> -O | ...
В нижестоящей программе (многоточие в приведенной выше команде) мне нужно разделить выходной поток на каждый файл. Я прочитал справочную страницу для bsdtar, но так и не смог указать байт-разделитель файлов.
В настоящее время я использую этот код ржавчины. Это работает только потому, что каждый файл имеет одну и ту же строку объявления XML (которую я отбрасываю).
struct FileIter<'a> {
buf_reader: StdinLock<'a>
}
impl FileIter<'_> {
fn next_file<'a>(&mut self, buf: &'a mut Vec<u8>) -> Option<&'a [u8]> {
buf.clear();
loop {
match self.buf_reader.read_until(b'?', buf) {
// This is the file deliminator
// <?xml version = "1.0" encoding = "UTF-8"?>\n
Ok(0) => { break None; }
Ok(_) => {
let buf_len = buf.len();
if buf_len >= 37 {
if &buf[buf_len - 37..buf_len] ==
b"<?xml version=\"1.0\" encoding=\"UTF-8\"?" {
buf.truncate(buf_len - 37);
if buf.len() > 2 {
break Some(&buf[2..]);
}
}
}
}
Err(err) => {
println!("{:?}", err);
break None;
}
}
}
}
}
Есть ли в bsdtar возможность указать байт разделителя файлов? Или есть более общий способ сделать это в Rust, который будет работать для всех файлов?
Я не на самом деле! Это такой очевидный ответ, я просто потянулся к тому, что знал. Спасибо !
Используя комментарий Lambda Fairy, я смог в значительной степени использовать точный пример из документации tar crate:
Груз.томл
...
[dependencies]
tar = "0.4.30"
flate2 = "1.0.19"
extern crate tar;
use std::fs::File;
use std::io::prelude::*;
use tar::Archive;
use flate2::read::GzDecoder;
fn main() {
let path = "file.tar.gz";
let tar_gz = File::open(path).unwrap();
let tar = GzDecoder::new(tar_gz);
let mut a = Archive::new(tar);
for file in a.entries().unwrap() {
// Make sure there wasn't an I/O error
let mut file = file.unwrap();
// Inspect metadata about the file
println!("{:?}", file.header().path().unwrap());
println!("{}", file.header().size().unwrap());
// files implement the Read trait
let mut s = String::new();
file.read_to_string(&mut s).unwrap();
println!("{}", s);
}
}
Рассматривали ли вы вместо этого использование нативной библиотеки Rust? Ставьте лайк crates.io/crates/tar