我真的被迫ReadToEnd()读取Ionic.Zlib.GZipStream的StreamReader吗?

Erw*_*yer 9 .net c# compression gzip streamreader

我使用以下代码解压缩GZipStream(使用DotNetZip库),其中fs是指向gz文件的文件流(使用FileMode.Open,FileAccess.Read,FileShare.ReadWrite):

using (var gz = new GZipStream(fs, CompressionMode.Decompress)) {
    using (var sr = new StreamReader(gz)) {
         header = sr.ReadLine();
    }
}
Run Code Online (Sandbox Code Playgroud)

但是如果直到最后才读取文件(我不喜欢这样做,因为文件可能很大),它会抛出

ZlibException("Bad CRC32 in GZIP trailer. (actual(EC084966)!=expected(8FC3EF16))")

在第一个结束括号(实际上当试图关闭()StreamReader时.

现在如果在关闭流读取器之前调用ReadToEnd()(或者我使用while(!sr.EndOfStream)循环读取所有行),它就可以工作.我观察到500 MB和200 kB压缩文件的相同行为,因此它似乎与文件大小无关.

非常欢迎您的见解!

这是一个简单的专用测试项目的链接.

它适用于System.IO.GZipStream库,所以这很奇怪.

Erw*_*yer 6

作为一个猜想,我怀疑如果 CRC 块位于文件的末尾,那么如果我中止读取流,它在处理流时无法验证完整性,因此会引发异常。

然而,这并不能解释为什么它在使用System.IO.GzipStream.

我在这里找到了 DotNetZip 源代码的相关部分,但似乎他们正在检查流是否被读取到最后(参见参考资料// Make sure we have read to the end of the stream)。然后,他们确实计算了一个 CRC32,因为异常消息显示了一个。

  • 最后一个注意事项 - 您不能将 Close 修改为继承的。相反,我将一个标志传递给 GZipConstructor 以指示是否应检查 CRC。以及指向 DotNetZip 讨论的链接... https://dotnetzip.codeplex.com/discussions/441615 - 谢谢大家! (2认同)