System.IO.Compression.GZipStream 或 System.IO.Compression.Deflate 是否与 zlib 压缩兼容?
8 回答
我遇到了 Git 对象的这个问题。在这种特殊情况下,它们将对象存储为带有 Zlib 标头的压缩 blob,该标头记录在RFC 1950中。您可以通过制作包含以下内容的文件来制作兼容的 blob:
- 带有值的两个标头字节(来自 RFC 1950 的 CMF 和 FLG)
0x78 0x01
CM
= 8 = 放气CINFO
= 7 = 32Kb 窗口FCHECK
= 1 = 此标头的校验和位
- C#的输出
DeflateStream
- 输入数据的 Adler32 校验和,
DeflateStream
大端格式(MSB 优先)
我做了自己的 Adler 实现
public class Adler32Computer
{
private int a = 1;
private int b = 0;
public int Checksum
{
get
{
return ((b * 65536) + a);
}
}
private static readonly int Modulus = 65521;
public void Update(byte[] data, int offset, int length)
{
for (int counter = 0; counter < length; ++counter)
{
a = (a + (data[offset + counter])) % Modulus;
b = (b + a) % Modulus;
}
}
}
差不多就是这样。
DotNetZip包括一个 DeflateStream、一个 ZlibStream 和一个 GZipStream,用于处理 RFC 1950、1951 和 1952。它们都使用 DEFLATE 算法,但每个帧和标题字节都不同。
作为一个优势,DotNetZip 中的流在压缩下不会表现出数据大小扩展的异常,这是针对内置流报告的。此外,没有内置的 ZlibStream,而 DotNetZip 为您提供了它,以便与 zlib 进行良好的互操作。
来自MSDN关于 System.IO.Compression.GZipStream:
此类表示 gzip 数据格式,它使用行业标准算法进行无损文件压缩和解压缩。
另一方面,zlib 中的 gz* 函数使用 gzip 格式。
所以 zlib 和 GZipStream 应该是可互操作的,但前提是你使用 zlib 函数来处理 gzip 格式。
据报道 System.IO.Compression.Deflate 和 zlib 不可互操作。
如果您需要处理 zip 文件(您可能不需要,但其他人可能需要它),您需要使用SharpZipLib或其他第三方库。
我使用 GZipStream 压缩来自 .NET XmlSerializer 的输出,并且使用 gunzip(在 cygwin 中)、winzip 和另一个 GZipStream 解压缩结果非常好。
作为参考,这是我在代码中所做的:
FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write);
using (GZipStream gzStream = new GZipStream(fs, CompressionMode.Compress))
{
XmlSerializer serializer = new XmlSerializer(typeof(MyDataType));
serializer.Serialize(gzStream, myData);
}
然后,在c#中解压
FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read);
using (Stream input = new GZipStream(fs, CompressionMode.Decompress))
{
XmlSerializer serializer = new XmlSerializer(typeof(MyDataType));
myData = (MyDataType) serializer.Deserialize(input);
}
在 cygwin 中使用“文件”实用程序表明,使用 GZipStream 和 GNU GZip 压缩的同一文件之间确实存在差异(可能是其他人在此线程中所述的标题信息)。然而,这种差异在实践中似乎并不重要。
gzip 是 deflate + 一些页眉/页脚数据,如校验和和长度等。因此,从一种方法可以使用另一种方法的流的意义上说,它们不兼容,但它们采用相同的压缩算法。
他们只是使用 zlib 或 deflate 算法压缩数据,但不提供某些特定文件格式的输出。这意味着如果您将流按原样存储到硬盘驱动器,您很可能无法使用某些应用程序(gzip 或 winrar)打开它,因为文件头(幻数等)不包含在流中,您应该自己写。
从 .NET Framework 4.5 开始,System.IO.Compression.DeflateStream
该类使用 zlib 库。
来自班级的MSDN 文章:
该类代表 Deflate 算法,它是无损文件压缩和解压缩的行业标准算法。从 .NET Framework 4.5 开始,DeflateStream 类使用 zlib 库。因此,它提供了更好的压缩算法,并且在大多数情况下,它提供的压缩文件比它在早期版本的 .NET Framework 中提供的更小。
我同意安德烈亚斯。您可能无法在外部工具中打开该文件,但如果该工具需要一个流,您或许可以使用它。您还可以使用相同的压缩类将文件放回去。