1

我正在使用bsdtar.tar.gz将包含许多(数百万)xml 文件的文件的内容通过管道 传输到标准输出。


目前我使用的命令是:

$ bsdtar -x -f <file.tar.gz> -O | ...

在下游程序(上述命令中的省略号)中,我需要将输出流分块到每个文件中。我已经阅读了 bsdtar 的手册页,但无论如何都看不到指定文件分隔符字节。

目前我正在使用这个 rust 代码。这仅适用于每个文件具有相同的 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 中适用于所有文件?

4

1 回答 1

1

使用 Lambda Fairy 的评论,我几乎可以使用tar crate 文档中的确切示例:

货运.toml


...

[dependencies]
tar = "0.4.30"
flate2 = "1.0.19"

main.rs

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);
    }
}
于 2020-12-14T05:17:22.830 回答