C# zlib压缩字节数组?

C# zlib压缩字节数组?,c#,bytearray,zlib,compression,C#,Bytearray,Zlib,Compression,我有一个未压缩的字节数组: 0E 7C BD 03 6E 65 67 6C 65 63 74 00 00 00 42 52 00 00 01 00 BB 14 8D 37 0A 00 00 01 00 00 05 E9 05 E9 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 81 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 00 00 01 00 00 00

我有一个未压缩的字节数组:

0E 7C BD 03 6E 65 67 6C 65 63 74 00 00 00 42 52 00 00 01
00 BB 14 8D 37 0A 00 00 01 00 00 05 E9 05 E9 00 00 00 00 00 00 00
00 00 00 00 01 00 00 00 00 00 81 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 05 00 00 01 00 00 00
我需要使用deflate算法(在zlib中实现)对其进行压缩,从我在C#中搜索的等价物可以使用GZipStream,但我根本无法匹配压缩结果

以下是压缩代码:

public byte[] compress(byte[] input)
{
    using (MemoryStream ms = new MemoryStream())
    {
        using (GZipStream deflateStream = new GZipStream(ms, CompressionMode.Compress))
        {
            deflateStream.Write(input, 0, input.Length);
        }
        return ms.ToArray();
    }
}
下面是上述压缩代码的结果:

public byte[] compress(byte[] input)
{
    using (MemoryStream ms = new MemoryStream())
    {
        using (GZipStream deflateStream = new GZipStream(ms, CompressionMode.Compress))
        {
            deflateStream.Write(input, 0, input.Length);
        }
        return ms.ToArray();
    }
}
1F 8B 08 00 00 04 00 ED BD 07 60 1C 49 96 25 26 2F 6D CA 7B 7F 4A F5 4A
D7 E0 74 A1 08 80 60 13 24 D8 90 40 10 EC C1 88 CD E6 92 EC 1D 69 47 23 29 AB 2A
81 CA 65 56 65 5D 66 16 40 CC ED 9D BC F7 DE 7B EF BD F7 DE 7B EF BD F7 BA 3B 9D
4E 27 F7 DF FF 3F 5C 66 64 01 6C F6 CE 4A DA C9 9E 21 80 AA C8 1F 3F 7E 7C 1F 3F
22 7E 93 9F F9 FB 7F ED 65 7E 51 E6 D3 F6 D7 30 CF 93 57 BF C6 AF F1 6B FE 5A BF
E6 AF F1 F7 FE 56 7F FC 03 F3 D9 AF FB 5F DB AF 83 E7 0F FE 35 23 1F FE BA F4 FE
AF F1 6B FC 1A FF 0F 26 EC 38 82 5C 00
以下是我期待的结果:

78 9C E3 AB D9 CB 9C 97 9A 9E 93 9A 5C C2 00 03 4E 41 0C 0C 8C 4C 8C 0C BB 45 7A
CD B9 80 4C 90 18 EB 4B D6 97 0C 28 00 2C CC D0 C8 C8 80 09 58 21 B2 00 65 6B 08
C8

我做错了什么,有人能帮我吗?

首先,一些信息:DEFLATE是压缩算法,它在中定义。DEFLATE分别在和中定义的ZLIB和GZIP格式中使用,它们本质上是DEFLATE bytestream周围的薄包装。包装器提供元数据,如文件名、时间戳、CRC或ADLER等

.NET的基类库实现了DeflateStream,当用于压缩时,它会生成原始DEFLATE bytestream。当用于解压时,它消耗原始的DEFLATE bytestream。NET还提供了一个GZipStream,它只是围绕该基础的一个GZIP包装器。.NET基类库中没有ZlibStream—没有任何生成或使用ZLIB的内容。这里有一些技巧,你可以四处搜索

NET中的deflate逻辑表现出一种行为异常,以前压缩的数据在“压缩”时实际上可能会被夸大。这是,和的来源。这可能是您看到的,因为压缩无效。微软已经拒绝了这个错误,因为虽然它在节省空间方面无效,但压缩流并不是无效的,换句话说,它可以被任何兼容的DEFLATE引擎“解压缩”

在任何情况下,正如其他人所说,不同压缩机产生的压缩ByTestStream不一定相同。这取决于压缩机的默认设置和应用程序指定的设置。即使压缩的ByTestStream不同,它们仍然可以解压缩到相同的原始ByTestStream。另一方面,您用来压缩的是GZIP,而您想要的似乎是ZLIB。虽然它们是相关的,但它们并不相同;不能使用GZipStream生成ZLIB ByTestStream。这是您看到的差异的主要来源


我想你想要一条ZLIB流

中的免费托管Zlib实现了对所有三种格式(DEFLATE、Zlib、GZIP)的压缩流。DeflateStream和GZipStream的工作方式与.NET内置类相同,其中有一个ZlibStream类,它的作用与您认为的相同。这些类中没有一个表现出我上面描述的行为异常


在代码中,它如下所示:

    byte[] original = new byte[] {
        0x0E, 0x7C, 0xBD, 0x03, 0x6E, 0x65, 0x67, 0x6C,
        0x65, 0x63, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x42, 0x52, 0x00, 0x00,
        0x01, 0x02, 0x01, 0x00, 0xBB, 0x14, 0x8D, 0x37,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x05, 0xE9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x81, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
        0x01, 0x00, 0x00, 0x00
    };

    var compressed = Ionic.Zlib.ZlibStream.CompressBuffer(original);
0000    78 DA E3 AB D9 CB 9C 97 9A 9E 93 9A 5C C2 00 03     x...........\...
0010    4E 41 0C 0C 8C 4C 8C 0C BB 45 7A CD 61 62 AC 2F     NA...L...Ez.ab./
0020    19 B0 82 46 46 2C 82 AC 40 FD 40 0A 00 35 25 07     ...FF,..@.@..5%.
0030    CE                                                  .
输出如下:

    byte[] original = new byte[] {
        0x0E, 0x7C, 0xBD, 0x03, 0x6E, 0x65, 0x67, 0x6C,
        0x65, 0x63, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x42, 0x52, 0x00, 0x00,
        0x01, 0x02, 0x01, 0x00, 0xBB, 0x14, 0x8D, 0x37,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x05, 0xE9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x81, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
        0x01, 0x00, 0x00, 0x00
    };

    var compressed = Ionic.Zlib.ZlibStream.CompressBuffer(original);
0000    78 DA E3 AB D9 CB 9C 97 9A 9E 93 9A 5C C2 00 03     x...........\...
0010    4E 41 0C 0C 8C 4C 8C 0C BB 45 7A CD 61 62 AC 2F     NA...L...Ez.ab./
0020    19 B0 82 46 46 2C 82 AC 40 FD 40 0A 00 35 25 07     ...FF,..@.@..5%.
0030    CE                                                  .
解压

    var uncompressed = Ionic.Zlib.ZlibStream.UncompressBuffer(compressed);

你可以看到


编辑

提出的问题是,为什么DotNetZip为前两个字节生成
78 DA
,而不是
78 9C
?这一区别无关紧要
78 DA编码为“最大压缩”,而
78 9C编码为“默认压缩”。正如您在数据中看到的,对于这个小示例,无论使用BEST还是DEFAULT,实际压缩的字节都是完全相同的。此外,在解压缩期间不使用压缩级别信息。它在您的应用程序中无效

如果您不想要“最大”压缩,换句话说,如果您非常想将
78 9C
作为前两个字节,即使这无关紧要,那么您就不能使用
CompressBuffer
便利功能,该功能使用最佳压缩级别。相反,您可以这样做:

  var compress = new Func<byte[], byte[]>( a => {
        using (var ms = new System.IO.MemoryStream())
        {
            using (var compressor =
                   new Ionic.Zlib.ZlibStream( ms, 
                                              CompressionMode.Compress,
                                              CompressionLevel.Default )) 
            {
                compressor.Write(a,0,a.Length);
            }

            return ms.ToArray();
        }
    });

  var original = new byte[] { .... };
  var compressed = compress(original);

很简单,您得到的是一个GZip头。您需要的是更简单的Zlib头。ZLib有用于GZip头、ZLib头或无头的选项。通常使用Zlib头,除非数据与磁盘文件关联(在这种情况下使用GZip头)。显然,.Net library无法写入Zlib头(即使这是文件格式中最常用的头)。试试看


您可以使用HexEdit(操作->压缩->设置)快速测试所有不同的zlib选项。看见我花了10分钟检查数据,只需将压缩的字节粘贴到HexEdit并解压缩即可。还尝试使用GZip和ZLib头压缩原始字节作为双重检查。请注意,您可能需要修改设置才能获得所需的字节。

为什么您希望不同的实现具有相同的输出?有许多方法可以压缩某些可以用同一解压器解压的内容。但是在您的例子中,zip流似乎输出了某种类型的头。不仅GZipStream的结果不同,而且它比未压缩的输入更大@犬夜叉,我已经明白了很多,这就是为什么我在寻找如何让它们成为液体,试图找出我做错了什么,因为我知道