2

许多命令行工具可让您-用于标准输入或标准输出。在 Rust 中是否有一种惯用的方式来支持它?

处理命令行参数的最常用方法似乎是clap. 如果我只想处理路径而不想要特殊情况-,我可以使用

use std::fs::File;
use std::io::Write;
use std::path::PathBuf;

use clap::Parser;

#[derive(clap::Parser, Debug)]
struct Args {
    #[clap(parse(from_os_str))]
    output: PathBuf,
}

fn main() -> std::io::Result<()> {
    let args = Args::parse();
    let mut file = File::create(args.output)?;
    file.write_all(b"Hello, world!")?;
    Ok(())
} 

然而,要处理-成为标准输出的情况,它就更复杂了。now的类型file必须是Box<dyn Write>因为stdout()不是 a File,而且正确设置它有点复杂。不难,但是那种需要多次复制并且容易搞砸的样板。

有没有一种惯用的方法来处理这个问题?

4

1 回答 1

1

这是你必须写进你的代码的东西。在许多情况下,不清楚-应该表示标准输入还是标准输出,并且需要程序的上下文来正确解释它。

在这种情况下,您实际上确实需要使用 a Box<dyn Write>&dyn Write或类似的)。如果您使用的是 Unix,您可以File通过使用(以及在 Windows 上类似但不相同的东西)从标准输入或输出创建一个对象FromRawFd,但您应该避免这样做,因为当您删除 a 时File,文件描述符已关闭,这不是正确的行为。

事实上,意外关闭一个标准文件描述符实际上会导致数据损坏,因为如果打开另一个文件,它将以可能的最低值(例如,1,用于标准输出)打开,然后println!可能会意外打印到新打开的文件。

所以dyn Write在这里使用 a 是正确的选择。在大多数情况下,性能影响不会很明显。

于 2022-01-05T22:59:00.970 回答