rust - Reading ZIP file in Rust causes data owned by the current function
问题描述
I'm new to Rust and am likely have a huge knowledge gap. Basically, I'm hoping to be create a utility function that would except a regular text file or a ZIP file and return a BufRead
where the caller can start processing line by line. It is working well for non ZIP files but I am not understanding how to achieve the same for the ZIP files. The ZIP files will only contain a single file within the archive which is why I'm only processing the first file in the ZipArchive.
I'm running into the the following error.
error[E0515]: cannot return value referencing local variable `archive_contents`
--> src/file_reader.rs:30:9
|
27 | let archive_file: zip::read::ZipFile = archive_contents.by_index(0).unwrap();
| ---------------- `archive_contents` is borrowed here
...
30 | Ok(Box::new(BufReader::with_capacity(128 * 1024, archive_file)))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function
It seems the archive_contents
is preventing the BufRead object from returning to the caller. I'm just not sure how to work around this.
file_reader.rs
use std::ffi::OsStr;
use std::fs::File;
use std::io::BufRead;
use std::io::BufReader;
use std::path::Path;
pub struct FileReader {
pub file_reader: Result<Box<BufRead>, &'static str>,
}
pub fn file_reader(filename: &str) -> Result<Box<BufRead>, &'static str> {
let path = Path::new(filename);
let file = match File::open(&path) {
Ok(file) => file,
Err(why) => panic!(
"ERROR: Could not open file, {}: {}",
path.display(),
why.to_string()
),
};
if path.extension() == Some(OsStr::new("zip")) {
// Processing ZIP file.
let mut archive_contents: zip::read::ZipArchive<std::fs::File> =
zip::ZipArchive::new(file).unwrap();
let archive_file: zip::read::ZipFile = archive_contents.by_index(0).unwrap();
// ERRORS: returns a value referencing data owned by the current function
Ok(Box::new(BufReader::with_capacity(128 * 1024, archive_file)))
} else {
// Processing non-ZIP file.
Ok(Box::new(BufReader::with_capacity(128 * 1024, file)))
}
}
main.rs
mod file_reader;
use std::io::BufRead;
fn main() {
let mut files: Vec<String> = Vec::new();
files.push("/tmp/text_file.txt".to_string());
files.push("/tmp/zip_file.zip".to_string());
for f in files {
let mut fr = match file_reader::file_reader(&f) {
Ok(fr) => fr,
Err(e) => panic!("Error reading file."),
};
fr.lines().for_each(|l| match l {
Ok(l) => {
println!("{}", l);
}
Err(e) => {
println!("ERROR: Failed to read line:\n {}", e);
}
});
}
}
Any help is greatly appreciated!
解决方案
似乎 archive_contents 正在阻止 BufRead 对象返回给调用者。我只是不确定如何解决这个问题。
您必须以某种方式重组代码。这里的问题是,档案数据是档案的一部分。所以不像file
,archive_file
不是一个独立的项目,而是一个指向档案本身的排序指针。这意味着存档需要比archive_file
此代码正确的寿命更长。
在 GC 语言中,这不是问题,archive_file
有一个参考,archive
并且无论它需要多久,它都会保持活力。对于 Rust 来说并非如此。
解决此问题的一种简单方法是将数据复制出archive_file
并复制到一个拥有的缓冲区中,您可以将其返回给父级。另一种选择可能是返回一个包装器(archive_contents, item_index)
,这将委托阅读(虽然可能有点棘手)。还有一个是没有file_reader
。
推荐阅读
- shared-directory - 访问多个负载平衡服务器上的共享文件夹
- sorting - 如何删除 JavaScript 中的所有多个值?
- python - 抓取中的意外输出
- python - 将函数动态添加到数组列
- javascript - 解构会创建一个新变量吗?
- python - python web请求超时错误(requests.exceptions.ConnectTimeout:HTTPSConnectionPool)
- godot - Kinematicbody2D 接触 Area2D?
- c# - Xamarin Firebase RTDB 和权限被拒绝 401
- javascript - 我想从 firebase 中的所有用户那里获取帖子 react native
- javascript - 我有一个错误“ER_BAD_FIELD_ERROR”将数据发送到我的数据库