13

System.IO.Compression.GZipStream 或 System.IO.Compression.Deflate 是否与 zlib 压缩兼容?

4

8 回答 8

17

我遇到了 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;
        }
    }
}

差不多就是这样。

于 2010-02-25T01:46:52.613 回答
15

DotNetZip包括一个 DeflateStream、一个 ZlibStream 和一个 GZipStream,用于处理 RFC 1950、1951 和 1952。它们都使用 DEFLATE 算法,但每个帧和标题字节都不同。

作为一个优势,DotNetZip 中的流在压缩下不会表现出数据大小扩展的异常,这是针对内置流报告的。此外,没有内置的 ZlibStream,而 DotNetZip 为您提供了它,以便与 zlib 进行良好的互操作。

于 2009-03-06T16:10:58.407 回答
10

来自MSDN关于 System.IO.Compression.GZipStream:

此类表示 gzip 数据格式,它使用行业标准算法进行无损文件压缩和解压缩。

zlib 常见问题解答

另一方面,zlib 中的 gz* 函数使用 gzip 格式。

所以 zlib 和 GZipStream 应该是可互操作的,但前提是你使用 zlib 函数来处理 gzip 格式。

据报道 System.IO.Compression.Deflate 和 zlib 不可互操作。

如果您需要处理 zip 文件(您可能不需要,但其他人可能需要它),您需要使用SharpZipLib或其他第三方库。

于 2008-09-16T09:18:21.490 回答
6

我使用 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 压缩的同一文件之间确实存在差异(可能是其他人在此线程中所述的标题信息)。然而,这种差异在实践中似乎并不重要。

于 2008-09-16T14:20:42.917 回答
3

gzip 是 deflate + 一些页眉/页脚数据,如校验和和长度等。因此,从一种方法可以使用另一种方法的流的意义上说,它们不兼容,但它们采用相同的压缩算法。

于 2008-09-16T08:34:48.693 回答
2

他们只是使用 zlib 或 deflate 算法压缩数据,但不提供某些特定文件格式的输出。这意味着如果您将流按原样存储到硬盘驱动器,您很可能无法使用某些应用程序(gzip 或 winrar)打开它,因为文件头(幻数等)不包含在流中,您应该自己写。

于 2008-09-16T08:28:49.877 回答
1

从 .NET Framework 4.5 开始,System.IO.Compression.DeflateStream该类使用 zlib 库。

来自班级的MSDN 文章

该类代表 Deflate 算法,它是无损文件压缩和解压缩的行业标准算法。从 .NET Framework 4.5 开始,DeflateStream 类使用 zlib 库。因此,它提供了更好的压缩算法,并且在大多数情况下,它提供的压缩文件比它在早期版本的 .NET Framework 中提供的更小。

于 2015-04-29T07:14:18.923 回答
0

我同意安德烈亚斯。您可能无法在外部工具中打开该文件,但如果该工具需要一个流,您或许可以使用它。您还可以使用相同的压缩类将文件放回去。

于 2008-09-16T08:31:52.380 回答