【发布时间】:2016-02-12 04:41:31
【问题描述】:
我在使用GZipStream 解压缩流过早结束的FreebaseRDF dump(30GB 压缩文本,480GB 未压缩)时遇到问题。没有抛出异常,只是 gz.Read() 开始返回零:
using(var gz = new GZipStream(File.Open("freebase-rdf-latest.gz", FileMode.Open), CompressionMode.Decompress))
{
var buffer = new byte[1048576];
int read, total = 0;
while ((read = gz.Read(buffer, 0, buffer.Length)) > 0)
total += read;
// total is 1945715682 here
// subsequent reads return 0
}
该文件可以很好地与其他应用程序一起解压(我尝试了 gzip 和 7zip)。
四处嗅探我在GZipStream documentation on MSDN之前的版本中发现了这个注释:
GZipStream 类可能无法解压缩导致的数据 超过 8 GB 的未压缩数据。
该注释已在最新版本的文档中删除。我正在使用 .NET 4.5.2,对我来说,在解压缩不到 2GB 之后,流就结束了。
有人知道更多关于这个限制的信息吗?文档中的语言暗示了其他先决条件,而不仅仅是解压缩超过 8gb - 我相当肯定我过去曾使用 GZipStream 来处理非常大的文件而没有遇到这个问题。
另外,任何人都可以推荐一个替代 GZipStream 的替代品,我可能会使用它来代替 System.IO.Compression?
更新
我尝试用 Ionic.Zlib (DotNetZip) 替换 System.IO.Compression 并得到相同的结果。
我尝试了 ICSharpCode.SharpZipLib 的 GZipInputStream 并在第一次读取时得到“未知块类型 6”。
我尝试了 SevenZipSharp,但没有用于读取的流装饰器 - 只有各种阻塞的“提取”方法来解压整个流,这不是我想要的。
另一个更新
使用 zlib1.dll,以下代码可以正确解压整个文件。它的运行时间也是 GZipStream 的 1/4!
var gzFile = gzopen("freebase-rdf-latest.gz", "rb");
var buffer = new byte[1048576];
int read, total = 0;
while ((read = gzread(gzFile, buffer, buffer.Length)) > 0)
total += read;
[DllImport("zlib1")] IntPtr gzopen(string path, string mode);
[DllImport("zlib1")] int gzread(IntPtr gzFile, byte[] buf, int len);
[DllImport("zlib1")] int gzclose(IntPtr gzFile);
..so 显然 .NET 中的所有现有 GZip 库都与 zlib 存在一些兼容性问题。我使用的 zlib1.dll 来自我的 mingw64 目录(我的机器上大约有十几个 zlib1.dll,但这是唯一的 64 位)。
【问题讨论】:
-
你编译的时候是x86还是x64?你也可以看看DeflateStream 吗?它在引擎盖下使用 zlib。不过,我不确定 DeflateStream 是否适用于您正在使用的内容。
-
@AdamSears x64 但我尝试了 32 位,但没有任何区别。 GZipStream encapsulates DeflateStream.
标签: c# .net gzipstream