首页 > 解决方案 > 管道输入到标准输入防止 read_line() 阻塞

问题描述

我正在尝试编写一个终端程序,该程序在 CSV 文件中进行管道传输,解析记录,然后根据它们启动测验。我的问题是,一旦我使用 将文件通过管道传输到我的命令行程序中io::stdin(),我就不能再使用io::stdin().read_line()它来获取用户输入,因为它会停止阻塞或等待用户输入。以下是最小可重现示例

use std::io;

fn main() {
    let stdin = io::stdin();
    println!("Please enter input");
    let mut user_input = String::new();
    stdin.read_line(&mut user_input).expect("Failed to get input");
    println!("The input was {}", user_input);
}

使用cargo run会导致正常的阻塞行为。使用echo 'Hello World' | cargo run原因read_line()不再阻塞整个程序的任何地方。

我认为这不是错误,而是标准输入的工作方式。谁能解释这种行为的细节以及是否有解决方法?

标签: ruststdin

解决方案


我认为这不是错误,而是标准输入的工作方式。

正确的。假设您可以针对 Unix 系统,解决方法是/dev/tty显式打开:

use std::io::{BufReader, BufRead};
use std::fs::File;

fn main() {
    // read piped stuff from stdin...

    // read interactive input from the user
    let mut input = BufReader::new(File::open("/dev/tty").unwrap());
    println!("Please enter input");
    let mut user_input = String::new();
    input.read_line(&mut user_input).expect("Failed to get input");
    println!("The input was {}", user_input);
}

请注意,以这种方式从用户那里获取输入并不是编写命令行程序的惯用方式,因为它不能自动化。相反,考虑支持命令行选项,像clap这样的 crate很方便。


推荐阅读