我正在尝试编写一个终端程序,该程序通过管道输入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()
不再在程序的任何地方阻塞。
我认为这不是一个错误,只是如何stdin工作。谁能解释一下这种行为的细节,是否有解决办法?
我认为这不是一个bug,只是stdin的工作方式。
正确的。假设您的目标是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会让它变得更方便。