io - 如果无法查找标准输入,我如何从标准输入或文件获取输入?

标签 io rust traits downcast

我正在将一些 Python 移植到 Rust 作为学习练习,需要从文件或标准输入中获取输入。我在一个结构中保留了我输入的句柄,所以我想我只是做一个 Box<io::Read>但我遇到了一种情况,我需要在输入中寻找,seek不是 Read 的一部分特征。我知道你不能在管道中查找,所以我现在继续假设只有当输入是文件时才会调用此方法,但我的问题是我无法检查它并在 Rust 中向下转换。

我知道我可以对两种输入类型使用枚举,但似乎应该有更优雅的方法来做到这一点。这就是我的问题,您如何做到这一点而不弄得一团糟?

是否可以将 stdin 或文件包装在同一种缓冲区中,这样我就可以只使用该类型而不用担心 IO 的类型?

最佳答案

我知道,您说过您想要更优雅且没有枚举的东西,但我认为枚举解决方案相当优雅。所以这是一种尝试:

use std::fs;
use std::io::{self, Read, Seek, SeekFrom};

enum Input {
    File(fs::File),
    Stdin(io::Stdin),
}

impl Read for Input {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        match *self {
            Input::File(ref mut file) => file.read(buf),
            Input::Stdin(ref mut stdin) => stdin.read(buf),
        }
    }
}

impl Seek for Input {
    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
        match *self {
            Input::File(ref mut file) => file.seek(pos),
            Input::Stdin(_) => {
                Err(io::Error::new(
                    io::ErrorKind::Other, 
                    "not supported by stdin-input",
                ))
            },
        }
    }
}

把这样的代码放在你的一些子模块中,不要再担心太多了。您可以像使用 File 一样使用 Input 类型的对象:无论如何您都必须处理查找错误,因此处理无法通过 stdin 查找应该非常容易.一个例子:

let arg = std::env::args().nth(1).unwrap();
let mut input = if arg == "--" {
    Input::Stdin(io::stdin())
} else {
    Input::File(fs::File::open(&arg).expect("I should handle that.."))
};

let mut v = Vec::new();
let _idc = input.read_to_end(&mut v);

match input.seek(SeekFrom::End(0)) {
    Err(_) => println!("oh noes :("),
    Ok(bytes) => println!("yeah, input is {} long", bytes),
}

关于io - 如果无法查找标准输入,我如何从标准输入或文件获取输入?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37223741/

相关文章:

Java IO,这些资源会自动关闭吗?

python - 在Python中多次计算文件中的行数

C# 似乎无法正确地将图像添加到 ziarchive

rust - 为实现特定类型的 trait 的泛型类型实现 trait

rust - 如何将大小特征插入集合

scope - 跨多个模块访问单例

haskell - I/O Monad 和 ByteString 到 Char 的转换?

scala - 具有覆盖抽象类型的蛋糕模式不适用于类型上限

reference - 如何将具体类型的迭代器特征对象转换为特征对象的迭代器特征对象?

rust - 如何为 `IntoIter` 绑定(bind) `<&Self as IntoIterator>` 类型?