功能说明
日志归档、接口响应和备份文件常用 gzip 减少体积。flate2 提供流式编码器与解码器,既可以包装文件,也可以写入内存缓冲区。本例演示内存往返:把重复文本写入 GzEncoder,得到带 gzip 头的压缩字节;再把压缩字节交给 GzDecoder 读取,比较解压结果与原文是否完全一致。
压缩器实现 Write,适合边生成边压缩;解压器实现 Read,适合边读边解析。两者都支持分块处理,不会一次性把大文件读入内存,本例为了简洁使用 Vec 作为目标。
关键代码
compress 创建写入 Vec 的 GzEncoder,压缩级别使用默认值,调用 write_all 写入全部输入,finish 结束流并返回底层缓冲区。finish 必须调用,否则尾部校验和与结束标记不会写出。decompress 用 GzDecoder 包装输入切片,read_to_end 读完全部内容。main 用重复字符串放大压缩效果,打印原始长度、压缩长度和是否一致,并以 Result 传播 IO 错误。
使用注意
gzip 只压缩,不加密,也不提供完整性以外的 authenticity,敏感数据仍需加密。解压不可信数据要限制输出大小,避免压缩炸弹耗尽内存;本例的 read_to_end 没有上限。多成员 gzip 流需要 MultiGzDecoder。压缩级别越高越慢,默认级别适合多数场景,应通过基准测试选择。gzip 头包含修改时间等元数据,若需要可复现构建,应使用固定头或比较解压后的内容。
验证方式
运行脚本,原文七百零四字节,压缩后通常只有几十字节,identical=true 表示往返完全一致。把输入改成长随机字节,压缩后可能更大,但 identical 仍应为 true。截断压缩数据末尾几个字节再解压,应返回 IO 错误而不是静默成功。
代码示例
use flate2::read::GzDecoder;
use flate2::write::GzEncoder;
use flate2::Compression;
use std::io::{self, Read, Write};
fn compress(input: &[u8]) -> io::Result<Vec<u8>> {
let mut encoder = GzEncoder::new(Vec::new(), Compression::default());
encoder.write_all(input)?;
encoder.finish()
}
fn decompress(input: &[u8]) -> io::Result<Vec<u8>> {
let mut decoder = GzDecoder::new(input);
let mut output = Vec::new();
decoder.read_to_end(&mut output)?;
Ok(output)
}
fn main() -> io::Result<()> {
let payload = b"hello gzip ".repeat(64);
let compressed = compress(&payload)?;
let restored = decompress(&compressed)?;
println!(
"{} -> {} bytes, identical={}",
payload.len(),
compressed.len(),
restored == payload
);
Ok(())
}