C++压缩解压:Zstandard (Zstd)压缩库
Zstd 压缩库
- 一、Zstandard (Zstd) 压缩库
-
- 1.1 什么是 Zstd?
- 1.2 与其他压缩算法的对比
- 二、Zstd 使用说明
-
- 2.1 命令行工具使用
- 2.2 编程库 (API) 使用 (以 C++ 为例)
- 三、Zstd 库主要类和函数
-
- 3.1 核心“类”(结构体)
-
- 1. 压缩上下文: `ZSTD_CCtx`
- 2. 解压缩上下文: `ZSTD_DCtx`
- 3. 字典结构体: `ZSTD_DDict` 和 `ZSTD_CDict`
- 4. 参数枚举: `ZSTD_cParameter` 和 `ZSTD_dParameter`
- 3.2 核心函数分类详解
-
- 1. 简单压缩/解压函数 (一次性 API)
- 2. 高级压缩/解压函数 (上下文 API)
- 3. 流式压缩/解压函数
- 4. 字典相关函数
- 5. 缓冲区大小计算函数
- 6. 参数设置函数
- 7. 错误处理函数
- 3.3 函数和类之间的关系总结
- 3.4 总结
- 四、示例
-
- 4.1 示例一:基础的一次性压缩和解压缩
- 4.2 示例二:使用上下文和字典进行高效压缩和解压缩
一、Zstandard (Zstd) 压缩库
1.1 什么是 Zstd?
Zstandard(简称 Zstd)是由 Facebook 开发的一种开源、高性能的实时压缩算法。它的设计目标是在极致的压缩和解压速度与优秀的压缩率之间取得最佳平衡。
自 2016 年首次发布以来,Zstd 凭借其卓越的性能,已被广泛应用于数据库、操作系统、容器技术、文件系统和网络协议等众多领域。
- 核心特性与优势
特性 | 描述 | 带来的好处 |
---|---|---|
极快的速度 | 压缩速度与 LZ4 相当,远快于 Gzip。解压速度是其王牌优势,几乎接近内存拷贝的速度。 | 非常适合对性能要求高的实时应用,如数据库查询、日志处理、游戏资产加载等。 |
可配置的压缩率 | 提供了广泛的压缩级别(通常从 -13 到 22),允许在速度和压缩率之间灵活权衡。 | - 低级别 (-5 到 3):追求极致速度,适合内存或高速缓存。 - 高级别 (10 到 22):追求高压缩率,可超过 Gzip,适合归档存储。 |
创新的字典压缩 | 支持“字典模式”,通过预先训练一个“字典”,可以极大提升对小数据块(如 JSON 消息、日志条目)的压缩率。 | 特别适合网络通讯、微服务和数据库行级压缩,能有效减少网络带宽和存储开销。 |
高压缩率 | 在相同的速度下,压缩率通常优于 Gzip。在压缩率与 Gzip 相当的情况下,速度快数倍。 | 在不牺牲太多性能的前提下,能获得比传统算法更好的空间节省。 |
流式处理 | 支持流式压缩和解压缩,能够处理远大于内存的文件或数据流。 | 适用于处理大型文件、网络流和管道数据。 |
跨平台与开源 | 完全开源(BSD 许可证),支持所有主流操作系统(Linux, Windows, macOS, BSD)和编程语言。 | 可以自由集成到任何商业或非商业项目中,社区活跃,维护更新及时。 |
- 适用场景
- 数据库: 压缩表空间、索引、日志,提升 I/O 效率。(如 MySQL, PostgreSQL, RocksDB)
- 操作系统与文件系统: 压缩内核镜像、软件包、文件系统透明压缩。(如 Linux, ZFS, Btrfs)
- 容器技术: 压缩容器镜像层,加速镜像分发。(如 Docker, Kubernetes)
- 网络传输: 压缩 API 响应、实时通讯数据,减少带宽消耗。
- 日志处理: 压缩大量日志数据,节省存储空间。
- 游戏开发: 压缩游戏资源(纹理、模型),加快加载速度。
Zstandard (Zstd) 是一个集高性能、高压缩率和高灵活性于一体的现代压缩库。无论是通过命令行快速处理文件,还是集成到程序中优化性能和存储,Zstd 都是一个极具吸引力的选择。它的“字典压缩”特性尤其在处理小数据块的场景中展现出巨大优势,使其成为下一代数据压缩技术的标杆。
1.2 与其他压缩算法的对比
为了让你有更直观的感受,这里是一个简化的对比表格:
算法 | 压缩速度 | 解压速度 | 压缩率 | 主要应用场景 |
---|---|---|---|---|
Zstd | 非常快 | 极快 | 非常好 | 通用场景首选,尤其适合需要快速解压的应用。 |
Gzip | 慢 | 中 | 好 | 最通用的标准,用于 Web 静态资源、日志、文件归档。 |
Brotli | 很慢 | 中 | 非常好 | 主要用于 Web 内容(HTTPS)的静态压缩,压缩率极高。 |
LZ4 | 极快 | 极快 | 一般 | 速度优先的场景,如内存数据库、高速缓存、实时数据传输。 |
7z (LZMA2) | 非常慢 | 慢 | 极高 | 用于最终归档和长期存储,不适合实时处理。 |
一句话总结:Zstd 重新定义了“快速压缩”的标准,它在速度和压缩率的综合表现上,目前在业界处于领先地位。
二、Zstd 使用说明
Zstd 的使用主要分为两种方式:命令行工具和编程库 (API)。
2.1 命令行工具使用
这是最简单直接的方式,适合在终端或脚本中使用。
前提:你需要先安装 Zstd 工具。
- Linux:
sudo apt install zstd
(Debian/Ubuntu) 或sudo yum install zstd
(CentOS/RHEL)。 - macOS:
brew install zstd
。 - Windows: 可以从 Zstd GitHub releases 页面下载预编译的二进制文件。
常用命令:
-
压缩文件
# 使用默认级别(通常是 3)压缩文件 file.txt,生成 file.txt.zst zstd file.txt# 使用最高压缩级别 19 压缩 zstd -19 file.txt# 使用最快压缩级别 1 压缩 zstd -1 file.txt# 压缩并删除原文件 zstd -f --rm file.txt
-
解压文件
# 解压 file.txt.zst,生成 file.txt unzstd file.txt.zst# 解压并删除原压缩文件 unzstd -f --rm file.txt.zst
-
查看压缩信息
# 显示压缩文件的详细信息,包括未压缩大小、压缩率等 zstd -l file.txt.zst
-
字典模式
# 1. 使用多个样本文件(sample1.json, sample2.json...)训练一个字典 dict zstd --train sample*.json -o dict# 2. 使用训练好的字典来压缩新的文件 zstd -D dict new_data.json# 3. 使用字典来解压 unzstd -D dict new_data.json.zst
2.2 编程库 (API) 使用 (以 C++ 为例)
如果你想在自己的程序中集成 Zstd,需要使用其 C API。C++ 可以无缝调用。
前提:
- 获取库文件:你可以下载源码编译,或使用包管理器安装开发包(如
libzstd-dev
)。 - 包含头文件:在你的代码中加入
#include "zstd.h"
。 - 链接库:在编译时链接 Zstd 库(如使用
-lzstd
标志)。
核心 API 函数:
ZSTD_compress
: 一次性压缩。ZSTD_decompress
: 一次性解压。ZSTD_compressBound
: 计算压缩所需的最大缓冲区大小。ZSTD_getFrameContentSize
: 获取解压后的准确大小。ZSTD_isError
/ZSTD_getErrorName
: 错误处理。
C++ 代码示例:压缩与解压
#include <iostream>
#include <string>
#include <vector>
#include "zstd.h" // Zstd 核心头文件// 辅助函数:检查 Zstd 操作是否出错
void checkZstdError(size_t result, const std::string& message) {if (ZSTD_isError(result)) {std::cerr << message << ": " << ZSTD_getErrorName(result) << std::endl;exit(EXIT_FAILURE);}
}int main() {// --- 1. 准备原始数据 ---std::string original_data = "Hello, Zstd! This is a test for compression and decompression.";std::cout << "Original Data: " << original_data << std::endl;std::cout << "Original Size: " << original_data.size() << " bytes" << std::endl;// --- 2. 压缩 (Compression) ---// a. 计算压缩需要的最大缓冲区大小size_t compress_buffer_size = ZSTD_compressBound(original_data.size());std::vector<char> compress_buffer(compress_buffer_size);// b. 执行压缩 (使用压缩级别 6)size_t compressed_size = ZSTD_compress(compress_buffer.data(), compress_buffer.size(),original_data.c_str(), original_data.size(),6 // Compression level);checkZstdError(compressed_size, "Compression failed");std::cout << "\nCompressed Size: " << compressed_size << " bytes" << std::endl;// --- 3. 解压 (Decompression) ---// a. 从压缩数据帧中获取原始数据大小unsigned long long decompress_size = ZSTD_getFrameContentSize(compress_buffer.data(), compressed_size);checkZstdError(decompress_size, "Failed to get decompressed size");// b. 分配解压缓冲区std::vector<char> decompress_buffer(decompress_size);// c. 执行解压size_t actual_decompressed_size = ZSTD_decompress(decompress_buffer.data(), decompress_buffer.size(),compress_buffer.data(), compressed_size);checkZstdError(actual_decompressed_size, "Decompression failed"