我想.zip使用zip crate读取不同线程中的文件。
extern crate zip;
use zip::ZipArchive;
use zip::read::ZipFile;
use std::fs::File;
use std::io::BufReader;
use std::thread;
fn compute_hashes(mut file: ZipFile) {
let reader_thread= thread::spawn(move || {
let mut reader = BufReader::new(file);
/* ... */
});
}
fn main() {
let mut file = File::open(r"facebook-JakubOnderka.zip").unwrap();
let mut zip = ZipArchive::new(file).unwrap();
for i in 0..zip.len() {
let mut inside = zip.by_index(i).unwrap();
if !inside.name().ends_with("/") { // skip directories
println!("Filename: {}", inside.name());
compute_hashes(inside);
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是编译器向我显示此错误:
extern crate zip;
use zip::ZipArchive;
use zip::read::ZipFile;
use std::fs::File;
use std::io::BufReader;
use std::thread;
fn compute_hashes(mut file: ZipFile) {
let reader_thread= thread::spawn(move || {
let mut reader = BufReader::new(file);
/* ... */
});
}
fn main() {
let mut file = File::open(r"facebook-JakubOnderka.zip").unwrap();
let mut zip = ZipArchive::new(file).unwrap();
for i in 0..zip.len() {
let mut inside = zip.by_index(i).unwrap();
if !inside.name().ends_with("/") { // skip directories
println!("Filename: {}", inside.name());
compute_hashes(inside);
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是对于类型也是一样std::fs::File。是否需要修理zip箱子或是否有其他方法?
这是板条箱API 的局限性,zip您无法真正更改任何内容。问题在于该文件ZipArchive是通过调用new并传递一个阅读器(即实现Read和的东西)创建的Seek。但这是读者的唯一要求(尤其是读者不必如此Clone)。因此,整个人ZipArchive只能拥有一个读者。
但是现在ZipArchive可以产生ZipFile实现Read自己的。如果整个ZipArchive只有一个读者,那怎么办?通过分享!存档和所有文件之间共享唯一的读取器。但是此共享不是线程节省!每个读者中都存储着对读者的可变引用ZipFile-这违反了Rust的核心原则。
这是板条箱的一个已知问题,正在GitHub问题跟踪器上进行讨论。
那你现在该怎么办?并不是很多,但是对于您的用例来说,几种可能性(如库作者所提到的)可能是可以的:
您可以先将整个文件解压缩到内存中,然后将原始数据发送到另一个线程进行计算。就像是:
let data = Vec::new();
BufReader::new(file).read_to_end(&mut data)?;
let reader_thread= thread::spawn(move || {
// Do stuff with `data`
});
Run Code Online (Sandbox Code Playgroud)
但是,如果您只想对所有文件计算便宜的哈希函数,则将内容加载到内存中的速度可能比动态计算哈希值要慢,并且如果文件很大,则可能不可行。
ZipArchive为每个线程创建一个。如果存档中有很多小文件,这可能会非常慢...
一个小提示:启动线程会花费时间。您通常不希望为每个工作单元启动一个线程,而是在线程池中维护固定数量的线程,在队列中管理工作并将工作分配给空闲的工作线程。该threadpool箱子可能满足您的需求。