
本文介绍使用 php 原生流式解压函数 `gzopen()` + `gzread()` 分块读取并解压超大 `.gz` 文件的方法,避免 `gzdecode()` 因一次性加载全文导致内存耗尽的问题,适用于无法调高 `memory_limit` 的生产环境。
当处理超过 200 MB 的 .gz 压缩文件(原始数据可能达 4 GB 以上)时,直接使用 gzdecode(@file_get_contents($file)) 必然触发 Allowed memory size exhausted 错误——因为该方式需将整个压缩流一次性读入内存再解码,完全违背流式处理原则。
✅ 正确方案是采用 PHP 内置的 gzip 流式 I/O 接口:
- gzopen():以只读模式打开 .gz 文件,返回资源句柄(类似 fopen()),不加载内容;
- gzread():按指定字节数(如 8192、65536)分块读取并自动解压,内存占用恒定可控;
- 配合 fwrite() 可边解压边写入目标文件,实现零内存峰值的“管道式”解压。
以下为完整、健壮的流式解压示例:
getMessage()); }
? 关键注意事项:
- ❌ 不要尝试 inflate_add() 或 zlib_decode():它们仍依赖完整输入缓冲区,无法规避内存限制;
- ✅ gzopen() / gzread() 是唯一被 PHP 官方支持的、真正流式、低内存的 gzip 解压方案;
- ⚠️ 确保 PHP 编译时启用了 zlib 扩展(绝大多数标准安装已默认启用);
- ? 若处理敏感数据,建议在解压后立即 unlink() 原始 .gz 文件,并对输出文件设置合适权限;
- ? chunkSize 建议设为 64KB~1MB:过小增加系统调用开销,过大仍可能轻微波动内存(但远低于全量加载)。
总结:面对 GB 级 .gz 文件且无法扩容 PHP 内存时,放弃所有“全量加载→解码”思路,坚定转向 gzopen() + gzread() 的流式范式——它不仅是可行解,更是 PHP 生态中唯一符合 Unix “do one thing well” 哲学的标准解法。










