提前道歉,这可能是一个微不足道的问题,但我什至不知道要寻找答案。我想读取可能经过或未经过 zip 压缩的文件。根据文件扩展名,我需要从简单的
Reader
或从 io::File
创建 BGZFReader<File>
。 Reader
会对任何实现Read+Seek
的东西感到满意。非工作代码应该如下所示:
let file_reader = if filename.as_ref().extension().unwrap_or_default() == "gz"
{
let in_file = BGZFReader::new(File::open(filename)?)?;
Reader::new(in_file)
}
else
{
let in_file = File::open(filename)?;
Reader::new(in_file)
};
但是这当然行不通,因为
Reader<File>
与Reader<BGZFReader<File>>
不一样。有没有办法说我的变量 file_reader
可以是 Reader
的任何实例,无论我使用的 Read+Seek
的具体实现是什么?
我想一般性地定义
file_reader
的原因是因为我需要打开多个文件然后传递给下游代码。每个都可以压缩或不压缩,因此为所有可能的组合编写 if/else
语句很快就会变得难以管理。
感谢评论中的提示,我想出了这个解决方案:
trait ReadAndSeek: Read+Seek {}
impl <R: Read+Seek> ReadAndSeek for R {}
fn open_file<P: AsRef<Path> + Debug>(path: P) -> Result<Reader<Box<dyn ReadAndSeek>>>
{
if path.as_ref().extension().unwrap_or_default() == "gz"
{
let in_file = BGZFReader::new(File::open(path)?)?;
Ok(Reader::new(Box::new(in_file)))
}
else
{
let in_file = File::open(path)?;
Ok(Reader::new(Box::new(in_file)))
}
}
和下游:
let read_file = open_file(read_bed)?;
let coord_file = open_file(coord_bed)?;
let processor = Processor::new(read_file, coord_file)?;
我最初不明白的两件事是:
Box
使用具有 dyn
特征的内部文件读取器