Delphi解压C# SharpZipLib压缩的zip文件报错如何解决
问题现象
需要解压C#应用通过SharpZipLib的ZipOutputStream生成的压缩文件,先后尝试两种Delphi实现均报错:
- 最初用Delphi自带zlib实现解压,非本程序zlib压缩的文件均触发"Data Error",原代码如下:
procedure TfrmDownload.DescompactaArquivo(aNomeArquivo: string); var _ArqCompact, _ArqDescompact: TFileStream; _Unzip: TDecompressionStream; function _GetNomeArquivoDesc: string; begin result := StringReplace(aNomeArquivo, '.zip', '', [rfIgnoreCase]); end; begin if ((FileExists(aNomeArquivo)) and (Pos('.zip', aNomeArquivo) > 0)) then begin _ArqCompact := TFileStream.Create(aNomeArquivo, fmOpenRead); try _ArqDescompact := TFileStream.Create(_GetNomeArquivoDesc, fmCreate); try _Unzip := TDecompressionStream.Create(_ArqCompact, 31); try _ArqDescompact.CopyFrom(_Unzip, 0); finally FreeAndNil(_Unzip); end; finally FreeAndNil(_ArqDescompact); end; DeleteFile(aNomeArquivo); finally FreeAndNil(_ArqCompact); end; end; end; - 改用
System.Zip单元实现解压,执行时触发"stream read error",代码如下:procedure TForm11.DecompactaZip(aNomeArquivo: string); var _Zip: TZipFile; begin _Zip := TZipFile.Create; try _Zip.Open(aNomeArquivo, zmRead); _Zip.ExtractAll(ExtractFilePath(aNomeArquivo)); _Zip.Close; finally _Zip.Free; end; end;
待解压文件的十六进制内容视图如下:
报错成因
两个报错的原因完全不同:
- 第一种zlib解压报错:实现逻辑从根本上错误。ZIP是归档封装格式,不是单纯的deflate/gzip压缩流,文件内包含本地文件头、分块压缩数据、中央目录、归档结束标记多段结构。代码直接把整个ZIP文件丢给zlib解压,还传入31参数让zlib按gzip格式识别头,等于把ZIP的结构信息也当成压缩数据解析,必然触发数据错误。
- 第二种System.Zip解压报错:格式兼容性不足。从十六进制头可以看到文件开头是
50 4B 03 04,是标准ZIP本地文件头魔数,但SharpZipLib默认配置下压缩文件时,会优先使用Deflate64(压缩方法ID为9) 算法,而Delphi自带的System.Zip单元仅支持存储(方法ID 0)、收缩(方法ID1)、标准Deflate(方法ID8)三种压缩算法,完全不支持Deflate64,读取到不识别的压缩数据就会抛出流读取错误。少数场景下SharpZipLib开启Zip64扩展、使用非UTF-8文件名编码未正确标记,也会触发同类报错,但绝大多数该场景下的报错核心诱因都是Deflate64不兼容。
可行解决方法
根据实际场景二选一即可:
- 方案1:调整压缩端配置(优先推荐,无额外依赖)
如果可以修改C#端的压缩逻辑,强制SharpZipLib生成全兼容的标准ZIP包即可,修改后现有System.Zip的代码可以直接正常运行。压缩时添加如下配置:ZipOutputStream zipStream = new ZipOutputStream(targetStream); zipStream.SetLevel(6); // 1-9的压缩等级可按需调整,不影响格式兼容性 zipStream.UseDeflate64 = false; // 关闭Deflate64,使用标准Deflate算法 zipStream.UseZip64 = UseZip64.Off; // 单文件小于4G的场景直接关闭Zip64扩展 - 方案2:替换Delphi端解压库
如果无法修改压缩端逻辑,直接替换自带的System.Zip为支持Deflate64的第三方解压库:- 优先选择开源免费的Abbrevia组件库,原生支持Deflate64、Zip64、多编码文件名,接口逻辑和自带TZipFile高度相似,改造成本极低。
- 也可以使用SevenZip组件调用7z动态库解压,全格式兼容,缺点是需要随程序发布7z.dll文件。
注意:不要尝试手动剥离ZIP文件头单独读取压缩块用zlib解压,Deflate64的流结构和标准Deflate不兼容,原生zlib本身不支持Deflate64解析,强行修改只会出现更多数据校验错误。
内容的提问来源于stack exchange,提问作者Leo Bruno
相关产品推荐
相关产品推荐

