为什么我实现的GZip压缩功能生成的压缩包被判定为无效格式?
核心问题原因
- 你在压缩流程未完成时提前读取了输出流内容:.NET的
GZipStream的Flush()方法仅会刷新当前缓冲的压缩数据到输出流,不会写入GZIP规范要求的尾部CRC校验值、原始数据长度等收尾元数据。你在GZipStream还未完成释放、收尾逻辑未执行时就读取MemoryStream的内容,得到的是不完整的GZIP数据。 - 不同工具的容错性差异:.NET自带的GZIP解压逻辑对残缺的尾部元数据做了兼容处理,所以本地压缩解压的往返流程可以正常运行;但Tiled、通用在线解压工具等严格遵循GZIP规范的实现,会校验尾部元数据的完整性,因此会判定你的压缩数据无效。
- 两份Base64结果不一致的原因:你生成的是残缺的GZIP数据,Tiled输出的是符合规范的完整GZIP数据,二者二进制内容本身存在差异,编码为Base64后自然不同。
修复方案
调整代码逻辑,等待GZipStream完成全部收尾流程后再读取输出流的内容,利用using的自动释放机制触发收尾逻辑即可,不需要手动调用多次Flush:
uint[] values = new uint[4]; values[0] = 1; values[1] = 1; values[2] = 1; values[3] = 1; byte[] memoryBytes; using (var memoryStream = new MemoryStream()) { using (var gzipStream = new GZipStream(memoryStream, CompressionMode.Compress)) using (var writer = new BinaryWriter(gzipStream)) { for (int i = 0; i < values.Length; i++) { writer.Write(values[i]); } } // 等GZipStream完全释放、写入尾部元数据后再读取流内容 memoryBytes = memoryStream.ToArray(); } var convertedString = Convert.ToBase64String(memoryBytes);
修改后输出的GZIP数据就会包含完整的尾部校验信息,可被Tiled等严格遵循GZIP规范的工具正常识别。
内容的提问来源于stack exchange,提问作者Victor Chelaru
相关产品推荐
相关产品推荐

