libzip是最轻量稳定且支持读写zip的主流库,c++可直接调用其c api;需注意路径安全、内存管理及错误码解析,避免误用zlib或minizip。

用 libzip 实现 zip 压缩和解压最直接
C++ 标准库不提供 zip 支持,必须依赖第三方库。libzip 是目前最轻量、稳定、且支持读写 zip 的主流选择(不是 zlib —— zlib 只处理 deflate 压缩算法,不处理 zip 文件结构)。它提供 zip_open、zip_add_file、zip_fopen 等接口,C++ 中可直接调用 C API(无需封装类也能用)。
常见错误是误用 zlib 或 minizip:zlib 本身不能创建/读取 .zip 文件头和目录结构;minizip(尤其旧版)对中文路径、ZIP64、密码支持弱,且 API 易出内存泄漏。
- Ubuntu/macOS 可直接
apt install libzip-dev或brew install libzip - Windows 推荐用 vcpkg:
vcpkg install libzip,链接时加-lzip - 编译时确保启用
ZIP_ENABLE_UTF8(默认开启),否则中文文件名会乱码
压缩多个文件到 zip:注意路径与内存管理
libzip 不自动递归扫描目录,需手动遍历文件并调用 zip_add_file。关键点在于:源路径传给 zip_add_file 的第二个参数(即 zip 内部路径)必须是相对路径,且不能以 / 开头,否则部分解压工具(如 Windows 资源管理器)会忽略该条目。
zip_t *za = zip_open("out.zip", ZIP_CREATE | ZIP_TRUNCATE, &err);
if (!za) { /* 错误处理 */ }
// 正确:内部路径为 "data/config.txt"
zip_source_t *src = zip_source_file(za, "/home/user/config.txt", 0, 0);
zip_file_add(za, "data/config.txt", src, ZIP_FL_OVERWRITE);
// 错误:内部路径以 "/" 开头 → zip_file_add(za, "/data/config.txt", ...)
zip_close(za);
-
zip_source_file第三个参数为 offset,0 表示从头读;第四个参数为 length,-1 表示读全部 - 每调用一次
zip_source_file都要配对zip_source_free,除非传给了zip_file_add(此时由 libzip 管理) - 若文件很大,避免一次性全读入内存;libzip 内部会流式压缩,但源文件必须保持可读状态直到
zip_close
解压 zip 到指定目录:路径安全与覆盖控制
解压时最容易出问题是路径穿越(path traversal)漏洞——攻击者构造含 ../ 的文件名,导致写入系统任意位置。libzip 提供 zip_fopen + zip_fread 手动读取,但不自动校验路径。必须自己检查 zip_get_name 返回的文件名是否合法。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 用
std::string_view检查文件名是否含".."或开头为"/"或含"\0" - 解压目标路径建议用
std::filesystem::weakly_canonical规范化,并确认最终路径在预期根目录下 - 用
ZIP_FL_ENC_STRICT标志打开 zip(zip_open(..., ZIP_FL_ENC_STRICT))可强制 UTF-8 解码,避免乱码引发的路径解析异常 - 若需覆盖已有文件,
zip_fopen默认不覆盖,需先std::filesystem::remove目标路径再写入
遇到 zip_error_t 错误码怎么查
libzip 几乎所有函数都通过 zip_error_t* 返回错误,而不是 errno。直接打印 zip_error_strerror 得到的是英文描述,但真正有用的是错误码本身(zip_error_code_zip 返回整数),对应 libzip 头文件里的 ZIP_ER_* 宏。
-
ZIP_ER_NOENT:文件不存在(比如zip_open找不到 zip 文件) -
ZIP_ER_INVAL:参数非法(如传了空指针给zip_add_file) -
ZIP_ER_MEMORY:分配内存失败(少见,但嵌入式环境需留意) -
ZIP_ER_READ:读取底层文件失败(权限不足、磁盘满、文件被占用)
别只看 zip_error_strerror 的字符串——它可能掩盖真实原因,比如解压时报 “Invalid argument”,实际是路径穿越检测失败触发了 ZIP_ER_INVAL。
路径处理和错误码映射是实际集成中最容易漏掉的环节,尤其是跨平台时 Windows 的反斜杠、macOS 的大小写敏感、Linux 的权限模型都会让同一段代码表现不同。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










