我有一个解压缩* .gz文件的方法:
using (FileStream originalFileStream = new FileStream(gztempfilename, FileMode.Open, FileAccess.Read))
{
using (FileStream decompressedFileStream = new FileStream(outputtempfilename, FileMode.Create, FileAccess.Write))
{
using (GZipStream decompressionStream = new GZipStream(originalFileStream, CompressionMode.Decompress))
{
decompressionStream.CopyTo(decompressedFileStream);
}
}
}
它工作得很好,但最近我收到了大小错误的文件包: 当我用7-zip打开它们时,它们的包装尺寸 ~1,600,000和尺寸 = 7(它应该是~20,000,000)。 因此,当我使用此代码提取它时,我只获得文件的一部分。但是当我使用7-zip解压缩此文件时,我会收到完整的文件。
如何在我的代码中处理这种情况?
答案 0 :(得分:2)
我的猜测是,当GZipping文件时,另一端会出错。看起来它没有正确设置ISIZE bytes。
ISIZE字节是有效GZip文件的最后四个字节,它位于32位CRC值之后,而后者又直接位于压缩数据字节之后。
7-Zip似乎可以抵御这些错误,而GZipStream
则不然。然而奇怪的是,7-Zip没有向您显示任何错误。它应该显示给你(用7-Zip 16.02 x64 / Win7测试)......
7-Zip始终使用打包文件的最后四个字节来确定原始解压缩文件的大小,而不检查文件是否有效以及为此读取的字节是否实际上是ISIZE字节。
您可以通过使用十六进制查看器检查GZipped文件的最后四个字节来验证这一点。对于您的示例,它们应该是07 00 00 00
。
如果您知道解压缩的原始文件的确切大小,则可以替换这些字节,以便它们指定正确的大小。例如,如果解压缩文件的大小为 20,000,078 ,其中 01312D4E 以十六进制( 0 - 填充到八位数),那些字节应为4E 2D 31 01
。
如果您不知道确切的尺寸,可以尝试使用最大值替换它们,即FF FF FF FF
。
然后再次尝试解压缩代码。
这显然只是解决问题的一个黑客。最好尝试修复GZips您收到的文件的代码,或者尝试找到比GZipStream
更强大的库。
答案 1 :(得分:1)
我使用了this库中的ICSharpCode.SharpZipLib.GZip.GZipInputStream而不是System.IO.Compression.GZipStream,它帮助了。
答案 2 :(得分:0)
您是否尝试过检查尺寸?即:
byte[] bArray;
using (FileStream f = new FileStream(tempFile, FileMode.Open))
{
bArray= new byte[f.Length];
f.Read(b, 0, f.Length);
}
此致
尝试:
GZipStream uncompressed = new GZipStream(streamIn, CompressionMode.Decompress, true);
FileStream streamOut = new FileStream(tempDoc[0], FileMode.Create, FileAccess.Write, FileShare.None);
答案 3 :(得分:0)
看起来这是GZipStream中的某种错误(它不会将原始文件长度写入文件的gz末尾)。 您需要更改使用GZipStream压缩文件的方式。 运作方式:
inputBytes = Encoding.UTF8.GetBytes(output);
using (var outputStream = new MemoryStream())
{
using (var gZipStream = new GZipStream(outputStream, CompressionMode.Compress))
gZipStream.Write(inputBytes, 0, inputBytes.Length);
System.IO.File.WriteAllBytes("file.xml.gz", outputStream.ToArray());
}
这种方式将导致您遇到错误(无论是否使用Flush()):
inputBytes = Encoding.UTF8.GetBytes(output);
using (var outputStream = new MemoryStream())
{
using (var gZipStream = new GZipStream(outputStream, CompressionMode.Compress))
{
gZipStream.Write(inputBytes, 0, inputBytes.Length);
System.IO.File.WriteAllBytes("file.xml.gz", outputStream.ToArray());
}
}
答案 4 :(得分:0)
关闭gZip流后,您可能需要调用decompressedStream.Seek()。