必须用zlib的gzopen/gzread/gzwrite操作.gz文件,fopen无法自动解压;gzopen失败返回Z_NULL而非NULL;gzwrite返回实际写入的未压缩字节数,须校验是否等于预期长度。
用
读写 gzip 文件,不是
zlib 不扩展标准 I/O,它提供独立的流接口。直接对
文件调用
只会读到二进制乱码,无法自动解压。必须用 zlib 自带的
、
、
等函数。
常见错误现象:
后用
读出全是空或非法字符;或者程序没报错但内容完全不对。
的 mode 参数和
类似,但只支持部分标识:
(解压读)、
(压缩写)、
/
也行,但不区分文本/二进制(gzip 流本身是二进制)
写入时默认使用 Z_BEST_COMPRESSION,如需控制压缩级别,得用
+
,但多数场景用默认即可
注意返回值:失败时
返回
,不是
,别用
粗暴判断(虽然常能过,但类型不匹配)
读取 gzip 文件内容到内存,避免边解压边解析的陷阱
很多需求其实是“把
解压成字符串再 parse”,这时候不该循环调用
拼接——容易丢字节、难控边界、还可能因缓冲区大小导致最后一块读不满。
更稳妥的做法是先获取原始压缩文件大小,再预分配足够内存,一次性解压进 buffer。
立即学习
“
C++免费学习笔记(深入)
”;
用
(POSIX)或
(Windows)获取
文件长度,这只是压缩后大小,不能当解压后容量用;真实解压后长度只能靠解压过程探测,或依赖上层协议(比如你知道它是个 2MB 的 JSON)
安全做法:用
扩大内部缓冲区(如设为 128KB),再配合循环
+
动态扩容,比手写 realloc 更稳
别忘了
,否则资源泄漏;C++ 中建议用 RAII 封装,例如
写 gzip 文件时,
返回值必须检查,且单位是字节数不是成功标志
返回实际写入的**未压缩字节数**,不是布尔值。如果返回值小于你传入的长度,说明写入失败或被截断——这在磁盘满、权限不足或管道中断时很常见,但容易被忽略。
C知道
CSDN推出的一款AI技术问答工具
下载
典型误用:
—— 这里只要写入 >0 字节就进分支,哪怕只写了 3 个字节。
正确做法:
错误时可用
和
辅助诊断:
,
是 zlib 错误码(如
、
)
写完务必调用
(虽
内部也会做,但显式调用可提前暴露压缩阶段问题)
跨平台编译时,zlib 的符号链接和库顺序不能颠倒
Linux/macOS 下链接命令写成
会失败:因为
在源文件之后,链接器找不到对
的引用。Windows 上用 MSVC 则要确保
在 linker input 里排在你的 obj 文件之后。
更隐蔽的问题是:某些发行版(如 Ubuntu)把 zlib 分成
(运行时)和
(动态库),开发机装了头文件却没装运行时库,编译通过但运行时报
。
Linux 推荐链接顺序:
(
放最后)
macOS 需加
且确认 Xcode 命令行工具已安装 zlib(通常自带)
静态链接更可靠:
,但注意 license 合规性
C++ 调 zlib 最容易卡在“以为在用标准 IO”和“忽略返回值含义”这两点上,尤其是
返回的是字节数而非状态码,这个反直觉设计让很多人掉坑里半天才反应过来。
gzopenfopen.gzfopengzopengzreadgzwritefopen("data.txt.gz", "r")fgetsgzopenfopen"r""w""rb""wb"gzopen64gzsetparamsgzopenZ_NULLNULLif (!fp)xxx.json.gzgzreadstat_stat64.gzgzbuffergzreadstd::vector::insertgzclosestruct gzfile { gzFile f; ~gzfile() { if(f) gzclose(f); } }gzwritegzwriteif (gzwrite(fp, buf, len)) { /* assume success */ }if (gzwrite(fp, buf, len) != len) { /* handle error */ }gzeofgzerrorint errnum; const char* msg = gzerror(fp, &errnum);errnumZ_MEM_ERRORZ_BUF_ERRORgzflush(fp, Z_FINISH)gzcloseg++ main.cpp -lz -o app-lzgzopenzlib.libzlib1g-devzlib1glibz.so.1: cannot open shared object fileg++ main.cpp -o app -lz-lz-lz-lz -static-libgcc -static-libstdc++gzwrite