我试图编写一个从文件或标准输入中获取输入的程序,具体取决于是否传递了命令行参数。为此,我使用了getopts,它允许你获得带有参数值的Option<String>
。如果值为Some(filename)
,我想打开该文件并在其上创建一个缓冲读取器。如果是None
,我想将流设置为标准输入。
let input: Box<Read> = match matches.opt_str("i") {
Some(ifname) => Box::new(BufReader::new(File::open(ifname).unwrap())),
None => Box::new(io::stdin()),
};
因此,输入类型需要为&read
或Box<Read>
,因为Stdin
和BufReader
是不兼容的类型。显然&Read
没有工作,因为没有变量实际上拥有足够长的范围内的对象。所以我尝试使用Box<Read>
,但这仍然让我错误地认为input
没有足够长的时间。
做这样的事情的生锈(生锈?质朴?)是什么样的?
MCVE:
use std::io;
use std::borrow::BorrowMut;
use std::io::{BufReader,BufWriter,Read,Write};
use std::fs::File;
fn rc4(key: &[u8], input: &mut Read, output: &mut Write) {
// Read and write here
}
fn main() {
let mut input: Box<Read> = match Some("file-from-parser.txt") {
Some(ifname) => Box::new(BufReader::new(File::open(ifname).unwrap())),
None => Box::new(io::stdin()),
};
rc4(&[1u8, 2, 3], input.borrow_mut(), &mut io::stdout());
}
答案 0 :(得分:4)
以下代码有效:
use std::io;
use std::io::{BufReader, Read, Write};
use std::fs::File;
fn rc4(key: &[u8], input: &mut Read, output: &mut Write) {
// Read and write here
}
fn main() {
let mut input: Box<Read> = match Some("file-from-parser.txt") {
Some(ifname) => Box::new(BufReader::new(File::open(ifname).unwrap())),
None => Box::new(io::stdin()),
};
rc4(&[1u8, 2, 3], &mut input, &mut io::stdout());
}
请注意,绝对没有理由使用borrow_mut()
,因为在必要时,对Box
指针的引用会自动强制引用其内部引用。此外,使rc4
使用对泛型类型的引用而不是特征对象更为惯用:
fn rc4<R: Read, W: Write>(key: &[u8], input: &mut R, output: &mut W)
甚至
fn rc4<R: Read, W: Write>(key: &[u8], input: R, output: W)
(这是有效的,因为如果&mut R
为Read
,R
为Read
,Write
同样适用;您可能需要写{ {1}}和/或mut input: R
取决于您使用的API)
上述代码无需更改这两个签名即可使用。
至于为什么mut output: W
不起作用,我没有任何想法。在我看来,它应该工作。也许这是与borrow_mut()
是特质对象这一事实的某种互动。
此外,有一种方法可以完全避免Box<Read>
:
Box
这里我们将每个阅读器存储在单独的变量中,并返回对其中一个的引用。