【问题标题】:Zlib-compatible compression streams?Zlib 兼容的压缩流?
【发布时间】:2008-09-16 08:25:33
【问题描述】:

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

【问题讨论】:

    标签: c# compression zlib


    【解决方案1】:

    我在使用 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;
            }
        }
    }
    

    差不多就是这样。

    【讨论】:

    • 谢谢先生!这有很大帮助。不过我没有把它变成一个类,只是把所有这些都放到一个函数中并使它成为静态的:P
    【解决方案2】:

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

    作为一个优势,DotNetZip 中的流在压缩下不会显示anomaly of expanding data size,根据内置流报告。此外,没有内置的 ZlibStream,而 DotNetZip 为您提供了它,以便与 zlib 进行良好的互操作。

    【讨论】:

      【解决方案3】:

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

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

      来自zlib FAQ

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

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

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

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

      【讨论】:

      • zip 文件与 zlib 压缩文件不同(压缩算法可能相同,但标头不同)
      • re:关于 zlib 和 DeflateStream 的“据报道不可互操作”。它们实际上是不可互操作的。涵盖该领域的 IETF RFC 共有三个:1950 年用于 ZLIB,1951 年用于 DEFLATE,1952 年用于 GZIP。 Deflate 是压缩算法。 ZLIB 和 GZIP 是不同的格式,它们定义了适用于压缩流的元数据,也就是“标头”。 zlib 库同时实现了 ZLIB 和 GZIP。有趣的是,ZLIB 和 GZIP 都可以使用 DEFLATE 作为压缩机制。 DeflateStream 类产生一个裸露的、无头的流。难怪我们都很困惑。
      【解决方案4】:

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

      【讨论】:

      • 像魅力一样工作!我用于性能测试的大数据集已从 55MB 压缩到仅 7.5MB,而没有明显的性能损失。附言如果将“文件”重命名为“file.gz”,它将成为一个完全有效的存档文件。您甚至可以使用任何存档工具修改其内容,并且使用您的方法将保持可反序列化。
      【解决方案5】:

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

      【讨论】:

        【解决方案6】:

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

        【讨论】:

          【解决方案7】:

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

          来自班级的MSDN article

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

          【讨论】:

            【解决方案8】:

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2022-01-10
              • 1970-01-01
              • 2012-11-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多