7 个版本 (2 个稳定版)
使用旧的 Rust 2015
1.0.1 | 2020 年 8 月 17 日 |
---|---|
1.0.0 | 2019 年 11 月 2 日 |
0.2.1 | 2018 年 4 月 14 日 |
0.2.0 | 2017 年 8 月 7 日 |
0.0.0 | 2017 年 8 月 3 日 |
#388 在 算法 中
229 每月下载量
在 11 个 包(4 个直接使用) 中使用
27KB
431 行
内容定义分块
该包提供了一种将字节流划分为块的方法,这些方法通过从内容本身选择分割点来实现。这意味着在流中添加或删除几个字节只会改变直接修改的块。这与仅仅每 n 个字节分割不同,因为在那种情况下,除非改变的字节数是 n 的倍数,否则每个块都不同。
内容定义分块对于数据去重很有用。它被用于许多备份软件,以及 rsync 数据同步工具。
该包公开了易于使用的功能,实现了标准 Iterator
特性,以便在输入流上迭代块,以及高效的零分配方法,这些方法重用内部缓冲区。
使用此包
首先,通过在您的 Cargo.toml
中添加以下内容来添加对包的依赖项
cdchunking = 1.0
并在您的 lib.rs
extern crate cdchunking;
然后使用特定方法创建一个 Chunker
对象,例如 ZPAQ 算法
use cdchunking::{Chunker, ZPAQ};
let chunker = Chunker::new(ZPAQ::new(13)); // 13 bits = 8 KiB block average
有几种方法可以从一些输入数据中获取块。
从内存缓冲区:迭代切片
如果您的整个输入数据都存储在内存中,您可以使用 slices()
方法。它将返回一个迭代器,该迭代器在缓冲区的切片上迭代,允许处理这些块而无需额外的分配。
for slice in chunker.slices(data) {
println("{:?}", slice);
}
从文件对象:将块读入内存
如果您正在从文件读取,或任何实现了 Read
接口的对象中读取,您可以使用 Chunker
直接读取整个数据块。使用 whole_chunks()
方法来获取数据块的迭代器,并以新的 Vec<u8>
对象的形式读取。
for chunk in chunker.whole_chunks(reader) {
let chunk = chunk.expect("Error reading from file");
println!("{:?}", chunk);
}
您还可以使用 all_chunks()
方法从文件中读取所有数据块并将它们收集到一个 Vec
(Vec
的向量)中。它将为您处理IO错误,如果任何一个数据块读取失败,将返回错误。
let chunks: Vec<Vec<u8>> = chunker.all_chunks(reader)
.expect("Error reading from file");
for chunk in chunks {
println!("{:?}", chunk);
}
从文件对象:零分配流式传输数据块
如果您正在从文件读取以写入到另一个地方,您可能认为分配中间 Vec
对象是不必要的。如果您希望 Chunker
从内部读取缓冲区提供数据块,而不分配任何其他内容,则可以这样做。在这种情况下,请注意,一个数据块可能会在多个读取操作之间分割。此方法可以适用于任何大小的数据块。
使用 stream()
方法来完成此操作。请注意,由于内部缓冲区被重复使用,我们无法实现 Iterator
特性,因此您需要使用 while 循环。
let mut chunk_iterator = chunker.stream(reader);
while let Some(chunk) = chunk_iterator.read() {
let chunk = chunk.unwrap();
match chunk {
ChunkInput::Data(d) => {
print!("{:?}, ", d);
}
ChunkInput::End => println!(" end of chunk"),
}
}