如何在Golang中解压C# zlib deflate生成的无头部压缩字节流?
问题根因
- 压缩参数导致格式不匹配:C#代码中
zStream.deflateInit第二个参数传-15,代表生成无zlib头、无尾部校验和的原始DEFLATE格式流,因此使用compress/zlib包解码时会直接报zlib: invalid header错误,该包仅支持标准zlib格式流。 - flate包报UnexpectedEOF的原因:C#代码调用
deflate时使用的是Z_SYNC_FLUSH标记,没有使用Z_FINISH生成DEFLATE流的结束标记,且返回的是固定长度的output数组,末尾可能包含未使用的空填充字节,compress/flate包默认期望读到完整的流结束标记,找不到时就会返回UnexpectedEOF错误,但此时已读取到的解压字节是有效的。
正确解压方案
package main import ( "bytes" "compress/flate" "io" ) func Decompress(input []byte) ([]byte, error) { r := flate.NewReader(bytes.NewReader(input)) defer r.Close() decompressed, err := io.ReadAll(r) // 原始DEFLATE流使用Z_SYNC_FLUSH且没有Z_FINISH结束标记时,会返回.ErrUnexpectedEOF // 此时已解压出的字节是有效的,确认输入完整的前提下可以忽略该错误 if err != nil && err != io.ErrUnexpectedEOF { return nil, err } return decompressed, nil }
补充说明
- 必须使用
compress/flate包处理原始DEFLATE流 - 忽略
io.ErrUnexpectedEOF的前提是你确认输入的压缩字节是完整的 - 可选优化:如果可以修改C#侧代码,建议压缩完成后将返回值修改为
output[:output.Length - zStream.avail_out],仅返回实际压缩生成的有效字节,避免末尾多余的空字节引发不必要的解码异常。
内容的提问来源于stack exchange,提问作者Rafael Leal
相关产品推荐
相关产品推荐

