从进程stdout读取而不将其全部放入内存中

kez*_*zos 1 process rust

我试图捕获外部工具的输出,该工具在一个单独的进程中运行.我想以非阻塞的方式这样做,因为输出大于内存.我看到你如何从Rust中的Process流输出?但我不知道该怎么办.我从这里复制了一个例子,但这似乎在继续之前将输出捕获到变量中.到目前为止,我有:

let path = "/Documents/Ruststuff/DB30_igh_badPE.bam";
let output = Command::new("samtools")
    .arg("view")
    .arg("-H")
    .arg(path)
    .stdin(Stdio::piped())
    .stdout(Stdio::piped())
    .spawn()
    .unwrap_or_else(|e| panic!("failed {}", e));

let mut s = String::new();
match output.stdout.unwrap().read_to_string(&mut s) {
    Err(why) => panic!("{}", Error::description(&why)),
    Ok(_) => print!("{}", s),
}
Run Code Online (Sandbox Code Playgroud)

是否可以stdout从子进程循环而不是使用匹配?就像是:

for line in &output.stdout {}
Run Code Online (Sandbox Code Playgroud)

She*_*ter 5

您不需要非阻塞IO来满足您的需求.您可以简单地使用缓冲读取器来循环输入行.这假设您总是需要一个完整的行,并且整行不是太多的数据:

use std::process::{Command, Stdio};
use std::io::{BufRead, BufReader};

fn main() {
    let mut child = Command::new("yes")
        .stdout(Stdio::piped())
        .spawn()
        .expect("Unable to spawn program");

    if let Some(ref mut stdout) = child.stdout {
        let lines = BufReader::new(stdout).lines().enumerate().take(10);
        for (counter, line) in lines {
            println!("{}, {:?}", counter, line);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

ChildStdoutRead为自己实现,但不为不可变引用(&ChildStdout).虽然我们拥有标准,但我们不想消耗它,所以我们需要某种参考.用于可变引用任何其它类型的是本身实现的,所以我们切换到可变引用.然后也需要变得可变.Read Readchild