Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Rust中从文件或stdin执行多态IO?_Io_Polymorphism_Rust - Fatal编程技术网

如何在Rust中从文件或stdin执行多态IO?

如何在Rust中从文件或stdin执行多态IO?,io,polymorphism,rust,Io,Polymorphism,Rust,我试图实现一个“多态的”Inputenum,它隐藏了我们是从文件还是从stdin读取。更具体地说,我正在尝试构建一个枚举,该枚举将有一个lines方法,该方法将依次“委托”调用封装在BufReader中的文件或StdInLock(两者都有lines()方法) 以下是枚举: enum Input<'a> { Console(std::io::StdinLock<'a>), File(std::io::BufReader<std::fs::File>

我试图实现一个“多态的”
Input
enum,它隐藏了我们是从文件还是从stdin读取。更具体地说,我正在尝试构建一个枚举,该枚举将有一个
lines
方法,该方法将依次“委托”调用封装在
BufReader
中的
文件
StdInLock
(两者都有
lines()
方法)

以下是枚举:

enum Input<'a> {
    Console(std::io::StdinLock<'a>),
    File(std::io::BufReader<std::fs::File>)
}
据我所知,我必须实现
BufRead
Read
两种特性,才能让它工作。这是我的尝试:

impl<'a> io::Read for Input<'a> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        match *self {
            Input::Console(ref mut c) => c.read(buf),
            Input::File(ref mut f) => f.read(buf),
        }
    }
}

impl<'a> io::BufRead for Input<'a> {
    fn lines(self) -> Lines<Self> {
        match self {
            Input::Console(ref c) => c.lines(),
            Input::File(ref f) => f.lines(),
        }
    }

    fn consume(&mut self, amt: usize) {
        match *self {
            Input::Console(ref mut c) => c.consume(amt),
            Input::File(ref mut f) => f.consume(amt),
        }
    }

    fn fill_buf(&mut self) -> io::Result<&[u8]> {
        match *self {
            Input::Console(ref mut c) => c.fill_buf(),
            Input::File(ref mut f) => f.fill_buf(),
        }
    }
}
我试着满足于:

match self {
    Input::Console(std::io::StdinLock(ref c)) => c.lines(),
    Input::File(std::io::BufReader(ref f)) => f.lines(),
}
。。。但这也不行


我在这里似乎真的有点不知所措。

这是最简单的解决方案,但将借用并锁定
Stdin

use std::fs::File;
use std::io::{self, BufRead, Read};

struct Input<'a> {
    source: Box<BufRead + 'a>,
}

impl<'a> Input<'a> {
    fn console(stdin: &'a io::Stdin) -> Input<'a> {
        Input {
            source: Box::new(stdin.lock()),
        }
    }

    fn file(path: &str) -> io::Result<Input<'a>> {
        File::open(path).map(|file| Input {
            source: Box::new(io::BufReader::new(file)),
        })
    }
}

impl<'a> Read for Input<'a> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.source.read(buf)
    }
}

impl<'a> BufRead for Input<'a> {
    fn fill_buf(&mut self) -> io::Result<&[u8]> {
        self.source.fill_buf()
    }

    fn consume(&mut self, amt: usize) {
        self.source.consume(amt);
    }
}

@A.B.的答案是正确的,但它试图符合OP的原始程序结构。我想为偶然发现这个问题的新手提供一个更具可读性的选择(就像我一样)

使用std::env;
使用std::fs;
使用std::io::{self,BufReader,BufRead};
fn main(){
让input=env::args().nth(1);
let reader:Box=匹配输入{
None=>Box::new(BufReader::new(io::stdin()),
Some(filename)=>Box::new(BufReader::new(fs::File::open(filename).unwrap())
};
对于读卡器中的行。行(){
println!(“{:?}”,行);
}
}

请参阅我从中借用代码的讨论。

您当前的方法将不起作用,因为
StdinLock
包含对
Stdin
对象的引用。如果您有时间,是否可以对此进行一点扩展?谢谢。另见:
match self {
    Input::Console(std::io::StdinLock(ref c)) => c.lines(),
    Input::File(std::io::BufReader(ref f)) => f.lines(),
}
use std::fs::File;
use std::io::{self, BufRead, Read};

struct Input<'a> {
    source: Box<BufRead + 'a>,
}

impl<'a> Input<'a> {
    fn console(stdin: &'a io::Stdin) -> Input<'a> {
        Input {
            source: Box::new(stdin.lock()),
        }
    }

    fn file(path: &str) -> io::Result<Input<'a>> {
        File::open(path).map(|file| Input {
            source: Box::new(io::BufReader::new(file)),
        })
    }
}

impl<'a> Read for Input<'a> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.source.read(buf)
    }
}

impl<'a> BufRead for Input<'a> {
    fn fill_buf(&mut self) -> io::Result<&[u8]> {
        self.source.fill_buf()
    }

    fn consume(&mut self, amt: usize) {
        self.source.consume(amt);
    }
}
let input = Input::file("foo.txt").unwrap();
for line in input.lines() {
    println!("input line: {:?}", line);
}
use std::env;
use std::fs;
use std::io::{self, BufReader, BufRead};

fn main() {
    let input = env::args().nth(1);
    let reader: Box<BufRead> = match input {
        None => Box::new(BufReader::new(io::stdin())),
        Some(filename) => Box::new(BufReader::new(fs::File::open(filename).unwrap()))
    };
    for line in reader.lines() {
        println!("{:?}", line);
    }
}