System.IO.Compression.GZipStream 或 System.IO.Compression.Deflate 是否与 zlib 压缩兼容?
8 回答
我遇到了 Git 对象的这个问题。在这种特殊情况下,它们将对象存储为带有 Zlib 标头的压缩 blob,该标头记录在RFC 1950中。您可以通过制作包含以下内容的文件来制作兼容的 blob:
- 带有值的两个标头字节(来自 RFC 1950 的 CMF 和 FLG)
0x78 0x01CM= 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 中提供的更小。
我同意安德烈亚斯。您可能无法在外部工具中打开该文件,但如果该工具需要一个流,您或许可以使用它。您还可以使用相同的压缩类将文件放回去。