【问题标题】:Continuously process child process' outputs byte for byte with a BufReader使用 BufReader 逐字节连续处理子进程的输出
【发布时间】:2021-05-22 21:34:16
【问题描述】:

我正在尝试与外部命令(在本例中为 exiftool)交互并逐字节读取输出,如下例所示。 如果我愿意首先读取所有输出并等待子进程完成,我可以让它工作,但使用 BufReader 似乎会导致无限期地等待第一个字节。我使用this example 作为使用 BufReader 访问标准输出的参考。

use std::io::{Write, Read};
use std::process::{Command, Stdio, ChildStdin, ChildStdout};

fn main() {
    let mut child = Command::new("exiftool")
        .arg("-@") // "Read command line options from file"
        .arg("-") // use stdin for -@
        .arg("-q") // "quiet processing" (only send image data to stdout)
        .arg("-previewImage") // for extracting thumbnails
        .arg("-b") // "Output metadata in binary format"
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .spawn().unwrap();

    {
        // Pass input file names via stdin
        let stdin: &mut ChildStdin = child.stdin.as_mut().unwrap();
        stdin.write_all("IMG_1709.CR2".as_bytes()).unwrap();
        // Leave scope:
        // "When an instance of ChildStdin is dropped, the ChildStdin’s underlying file handle will
        // be closed."
    }

    // This doesn't work:
    let stdout: ChildStdout = child.stdout.take().unwrap();
    let reader = std::io::BufReader::new(stdout);
    for (byte_i, byte_value) in reader.bytes().enumerate() {
        // This line is never printed and the program doesn't seem to terminate:
        println!("Obtained byte {}: {}", byte_i, byte_value.unwrap());
        // …
        break;
    }

    // This works:
    let output = child.wait_with_output().unwrap();
    for (byte_i, byte_value) in output.stdout.iter().enumerate() {
        println!("Obtained byte {}: {}", byte_i, byte_value);
        // …
        break;
    }
}

【问题讨论】:

  • @FrancisGagné 解决了,非常感谢!

标签: rust process command pipe


【解决方案1】:

您没有关闭孩子的标准输入。您的 stdin 变量是一个可变引用,删除它对引用的 ChildStdin 没有影响。

使用child.stdin.take() 代替child.stdin.as_mut()

    {
        // Pass input file names via stdin
        let stdin: ChildStdin = child.stdin.take().unwrap();
        stdin.write_all("IMG_1709.CR2".as_bytes()).unwrap();
        // Leave scope:
        // "When an instance of ChildStdin is dropped, the ChildStdin’s underlying file handle will
        // be closed."
    }

【讨论】:

    猜你喜欢
    • 2022-11-05
    • 1970-01-01
    • 2019-06-08
    • 2013-01-27
    • 2020-11-12
    • 2015-04-12
    • 1970-01-01
    • 2011-02-17
    相关资源
    最近更新 更多