写入Rust中的文件或标准输出

Nei*_*eil 6 file stdio rust

我正在学习Rust,我有点难过.

我正在尝试为用户提供将输出写入stdout或提供的文件名的选项.

我开始与那正是使用给出的示例代码extra::getopts位于这里.从那里,在do_work函数中,我正在尝试这样做:

use std::io::stdio::stdout;
use std::io::buffered::BufferedWriter;

fn do_work( input: &str, out: Option<~str> ) {
    println!( "Input:  {}", input );
    println!( "Output: {}", match out {
        Some(x) => x,
        None    => ~"Using stdout"
    } );
    let out_writer = BufferedWriter::new( match out {
        // I know that unwrap is frowned upon, 
        // but for now I don't want to deal with the Option.
        Some(x) => File::create( &Path::new( x ) ).unwrap(),
        None    => stdout()
    } );
    out_writer.write( bytes!( "Test output\n" ) );
}
Run Code Online (Sandbox Code Playgroud)

但它输出以下错误:

test.rs:25:43: 28:6 error: match arms have incompatible types: expected `std::io::fs::File` but found `std::io::stdio::StdWriter` (expected struct std::io::fs::File but found struct std::io::stdio::StdWriter)
test.rs:25     let out_writer = BufferedWriter::new( match out {
test.rs:26         Some(x) => File::create( &Path::new( x ) ).unwrap(),
test.rs:27         None    => stdout()
test.rs:28     } );
test.rs:25:22: 25:41 error: failed to find an implementation of trait std::io::Writer for [type error]
test.rs:25     let out_writer = BufferedWriter::new( match out {
                            ^~~~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)

但我不明白的是什么问题,因为这两个FileStdWriter落实Writer特质.谁能解释我做错了什么?

谢谢!

Pau*_*rth 8

Rust自2014年以来发生了很多变化,所以这里有一个适用于Rust 1.15.1的答案:

let out_writer = match out {
    Some(x) => {
        let path = Path::new(x);
        Box::new(File::create(&path).unwrap()) as Box<Write>
    }
    None => Box::new(io::stdout()) as Box<Write>,
};
Run Code Online (Sandbox Code Playgroud)

这与@ Arjan的答案几乎相同,除了~被替换为Box,并且一些名称已经改变.我要离开了BufferedWriter,但如果你想要那个,我相信它现在被命名了BufWriter.


Arj*_*jan 5

是的,都实现Write,但问题是BufWriter期待一个类型T实现Writer,而T不能FileStdout在同一时间.

您必须将两者都转换为公共类型(或者,Box<Write>或者&Write因为您不能返回必须使用的引用Box):

fn do_work(input: &str, out: Option<String>) {
    let mut out_writer: Box<Write> = BufWriter::new(match out {
        Some(ref x) => Box::new(File::create(&Path::new(x)).unwrap()),
        None => Box::new(stdout()),
    });
    out_writer.write(b"Test output\n").unwrap();
}
Run Code Online (Sandbox Code Playgroud)

您还应该正确处理错误,而不仅仅是使用unwrap(为简单起见,在示例中使用).

  • 由于写了这个答案,因此从Rust中删除了波形符'〜',并引入了一些有关DST的更改.我们将不胜感激. (3认同)