问题描述
我正在尝试与外部命令(在本例中为 exiftool)交互并逐字节读取输出,如下例所示。 如果我愿意首先读取所有输出并等待子进程完成,我可以让它工作,但使用 BufReader 似乎会导致无限期地等待第一个字节。我使用 this example 作为使用 BufReader 访问 stdout 的参考。
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_value);
// …
break;
}
}
解决方法
您没有关闭孩子的标准输入。您的 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."
}