file - 使用进度条提取档案 - 可变借用错误
问题描述
我正在尝试提取 .tar.bz 文件(实际上是 .tar.whatever),并且还能够获得 xx% 的进度报告。到目前为止,我有这个:
pub fn extract_file_with_progress<P: AsRef<Path>>(&self, path: P) -> Result<()> {
let path = path.as_ref();
let size = fs::metadata(path)?;
let mut f = File::open(path)?;
let decoder = BzDecoder::new(&f);
let mut archive = Archive::new(decoder);
for entry in archive.entries()? {
entry?.unpack_in(".")?;
let pos = f.seek(SeekFrom::Current(0))?;
}
Ok(())
}
这个想法是用来pos/size
获取百分比,但是编译上面的函数会让我得到错误cannot borrow f as mutable because it is also borrowed as immutable
。我理解错误的含义,但我并没有真正使用f
可变;我只使用 seek 函数来获取当前位置。
有没有办法解决这个问题,要么强制编译器忽略可变借用,要么以某种不可变的方式获取位置?
解决方案
文件有点特殊。通常的read()
and方法(在,seek()
和trait 上定义)采用可变引用:write()
Read
Seek
Write
self
fn read(&mut self, buf: &mut [u8]) -> Result<usize>
fn seek(&mut self, pos: SeekFrom) -> Result<u64>
fn write(&mut self, buf: &[u8]) -> Result<usize>
但是,所有提到的特征也都实现了&File
,即对文件的不可变引用:
因此,即使您只有对该文件的只读引用,您也可以修改该文件。对于这些实现,Self
类型是&File
,因此self
通过可变引用接受实际上意味着接受 a &mut &File
,对文件引用的可变引用。
您的代码传递&f
给BzDecoder::new()
,创建一个不可变的借用。稍后您调用f.seek(SeekFrom::Current(0))
,它通过可变引用传递f
给。seek
但是,这是不允许的,因为您已经有了文件的不可变借用。解决方案是改为使用Seek
实现&File
:
(&mut &f).seek(SeekFrom::Current(0))
或者稍微简单一点
(&f).seek(SeekFrom::Current(0))
这只会创建第二个不可变借用,这是 Rust 的引用规则所允许的。
我创建了一个Playground 示例来证明这很有效。如果你替换(&f)
为f
你得到你最初得到的错误。
推荐阅读
- apollo - 有没有办法从突变更新函数中获取变量?
- jquery - 我无法从单个表单字段中获取输入数组
- javascript - 如何将javascript代码中的变量打印到html正文中?
- aws-sdk - Amazon Athena - 使用 Java SDK 将列名称映射到值
- r - 采购时 RStudio 中的环境
- python - d.get(key) 与 d[key] 的 Python defaultdict 有什么区别?
- mysql - 使用 MySQL 的 RDS 上的大量数据传输使用
- python - 如何从图层创建 keras 模型?
- csvhelper - 当标头不存在时,如何使用 CsvHelper ClassMap 将默认值设置为字段?
- sas - 如何在一串可能拼错的单词中搜索单词