在C++中处理ZIP压缩包:从入门到进阶
在现代C++开发中,经常需要打包和解压数据。无论是保存配置、传输日志还是创建备份——处理ZIP压缩包仍然是最受欢迎的技能之一。在本文中,我们将详细讲解两个流行的库:libzip(官方、功能强大)和miniz(轻量、单头文件)。您将学习如何创建、读取和修改ZIP压缩包,并获得现成的代码示例。
为什么选择ZIP?
ZIP格式是无损压缩的事实标准。它受到所有操作系统的支持,可以存储多个文件和文件夹,并支持加密和流式处理。C++没有内置的ZIP支持(除了实验性的<filesystem>),因此我们使用第三方库。
libzip库:处理复杂任务的强大工具
libzip是一个跨平台的C语言库,具有优秀的C++兼容API。它提供对压缩包的完全控制:创建、读取、修改、删除文件,以及处理注释和元数据。
安装libzip(Linux/macOS)
# Ubuntu/Debiansudo apt-get install libzip-dev
# macOS (Homebrew)brew install libzip
# Windows — 通过vcpkg或从libzip.org网站下载示例1:创建ZIP压缩包
创建一个名为example.zip的压缩包,并向其中添加一个文本文件。
#include <zip.h>#include <iostream>#include <string>
int main() { // 以写入模式打开压缩包(APPEND_CREATE将创建新文件) int err = 0; zip_t *archive = zip_open("example.zip", ZIP_CREATE | ZIP_TRUNCATE, &err); if (!archive) { std::cerr << "创建压缩包时出错:" << err << std::endl; return 1; }
// 文件数据 const char *content = "来自PythonLib的问候!"; zip_source_t *source = zip_source_buffer(archive, content, strlen(content), 0); if (!source) { std::cerr << "无法创建数据源" << std::endl; zip_close(archive); return 1; }
// 将文件添加到压缩包 zip_int64_t index = zip_file_add(archive, "hello.txt", source, ZIP_FL_OVERWRITE); if (index < 0) { std::cerr << "无法添加文件:" << zip_strerror(archive) << std::endl; zip_source_free(source); zip_close(archive); return 1; }
// 关闭压缩包 zip_close(archive); std::cout << "压缩包创建成功!" << std::endl; return 0;}示例2:解压压缩包中的所有文件
读取压缩包并将所有文件提取到当前目录。
#include <zip.h>#include <iostream>#include <fstream>
int main() { int err = 0; zip_t *archive = zip_open("example.zip", ZIP_RDONLY, &err); if (!archive) { std::cerr << "打开压缩包时出错" << std::endl; return 1; }
zip_int64_t num_entries = zip_get_num_entries(archive, 0); for (zip_int64_t i = 0; i < num_entries; ++i) { // 获取文件名 const char *filename = zip_get_name(archive, i, 0); if (!filename) continue;
// 打开压缩包内的文件 zip_file_t *zf = zip_fopen_index(archive, i, 0); if (!zf) { std::cerr << "无法打开:" << filename << std::endl; continue; }
// 读取数据并写入文件 char buffer[1024]; std::ofstream out(filename, std::ios::binary); zip_int64_t bytes_read; while ((bytes_read = zip_fread(zf, buffer, sizeof(buffer))) > 0) { out.write(b