8 个版本 (4 个重大更新)
0.5.1 | 2022年9月6日 |
---|---|
0.5.0 | 2022年9月6日 |
0.4.0 | 2021年6月4日 |
0.3.1 | 2020年10月26日 |
0.1.0 | 2020年6月19日 |
#9 in #zip
6,179 每月下载量
在 2 crates 中使用
64KB
976 行
piz:一个并行实现的Zip(在Rust中)
piz是一个ZIP归档读取器,它设计用来使用简单的API并发地解压缩任意数量的文件
// For smaller files,
//
// let bytes = fs::read("foo.zip")
// let archive = ZipArchive::new(&bytes)?;
//
// works just fine. Memory map larger files!
let zip_file = File::open("foo.zip")?;
let mapping = unsafe { Mmap::map(&zip_file)? };
let archive = ZipArchive::new(&mapping)?;
// We can iterate through the entries in the archive directly...
//
// for entry in archive.entries() {
// let mut reader = archive.read(entry)?;
// // Read away!
// }
//
// ...but ZIP doesn't guarantee that entries are in any particular order,
// that there aren't duplicates, that an entry has a valid file path, etc.
// Let's do some validation and organize them into a tree of files and folders.
let tree = as_tree(archive.entries())?;
// With that done, we can get a file (or directory)'s metadata from its path.
let metadata = tree.lookup("some/specific/file")?;
// And read the file out, if we'd like:
let mut reader = archive.read(metadata)?;
let mut save_to = File::create(&metadata.file_name)?;
io::copy(&mut reader, &mut save_to)?;
// Readers are `Send`, so we can read out as many as we'd like in parallel.
// Here we'll use Rayon to read out the whole archive with all cores:
tree.files()
.par_bridge()
.try_for_each(|entry| {
if let Some(parent) = entry.file_name.parent() {
// Create parent directories as needed.
fs::create_dir_all(parent)?;
}
let mut reader = archive.read(entry)?;
let mut save_to = File::create(&entry.file_name)?;
io::copy(&mut reader, &mut save_to)?;
Ok(())
})?;
Zip是一个有趣的归档格式:与Linux领域常见的压缩tar包(如*.tar.gz
,*.tar.zst
等)不同,Zip归档中的每个文件都是独立压缩的,中心目录告诉我们如何找到它们。这允许我们只要能同时从多个位置读取,就可以同时提取多个文件。
用户可以选择将整个归档读入内存,或者对于更大的归档,可以使用内存映射文件。(在64位系统上,即使文件比物理RAM大得多,这也允许我们将归档视为一个连续的字节范围。32位系统受地址空间限制,归档大小不能超过4GB,但只要归档足够小,piz应该表现得很好。)
示例
查看unzip/
,其中包含一个简单的CLI示例,该示例将提供的文件解压缩到当前目录中。
测试
test_harness/
包含一些针对几个输入的烟雾测试,例如:
- 一些文本文件的基本、“Hello, Zip!”归档
- 与一些垃圾数据预置相同的归档
- 包含文件大于2^32字节的Zip64归档
如果没有找到这些文件,它将使用shell脚本创建它们(该脚本假定Unix环境)。
未来计划
Piz目前为每个文件提供有限的元数据(路径、大小、CRC32、最后修改时间等)。应稍后添加更多信息,如文件权限。也可以添加对DEFLATE以外的压缩算法(如Bzip2)的支持。
感谢
许多感谢
-
汉斯·韦尔博格(Hans Wennborg)对他们的出色文章,Zip文件:历史、解释和实现
-
马蒂·范·德·内斯(Mathijs van de Nes)的 zip-rs,这是本项目的灵感来源,也是Rust中Zip解码器的一个很好的例子
依赖关系
~1.9–3MB
~51K SLoC