Zlib压缩不兼容C与C#的实现

Zlib压缩不兼容C与C#的实现

本文介绍了Zlib压缩不兼容C与C#的实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用2个与zlib算法兼容的最合法的库在C#中解压缩使用zlib算法压缩的数据,并且抛出类似的异常。

I'm trying to decompress data compressed with zlib algorithm in C# using 2 most legitimate libraries compatible with zlib algorithm and I got similar exception thrown.

使用DotNetZip:

Using DotNetZip:

Ionic.Zlib.ZlibException: Bad state (invalid stored block lengths)

使用Zlib.Net:

Using Zlib.Net:

inflate: invalid stored block lenghts

,但使用与输入 zlib-flate 命令仅使用默认参数,可以很好地工作并解压缩,而没有任何警告(输出正确):

but using same data as input to zlib-flate command on linux using only default parameters, works great and decompressed without any warnings (output is correct):

zlib-flate -uncompress < ./dbgZlib

任何建议我可以做什么以便在C#中解压缩此数据,或者为什么要真正解压缩在这种情况下失败?

Any suggestions what I can do in order to decompress this data in C# or why actually decompression failing in this case?

压缩数据为十六进制:

root@localhost:~# od -t x1 -An ./dbgZlib |tr -d '\n '
789c626063520b666060606262d26160d05307329999e70a6400e93c2066644080cf8c938c0c0c4d0d0d0d2d839c437c02dcfd0c0c0c11d28ea121013e7e41860ce18e210640e06810141669c080051840012eb970d790800090f99eee409ea189025e806c8e8b5354a89b13d81c136ca60f3a000e5fd6af0fb14a3221873e96400506374cd6c7d52dc8d98980657e7e06460ace0a4ce86e80da9f0249030edf816c16481ab06b60404f03931169c0cdc728c0db0fd928681a3042a481480347336c6e21320d78fb8155195a9090067ca3420387771a400a546aa70100000000ffff

压缩数据为base64:

Compressed data as base64:

root@localhost:~# base64 ./dbgZlib
eJxiYGNSC2ZgYGBiYtJhYNBTBzKZmecKZADpPCBmZECAz4yTjAwMTQ0NDS2DnEN8Atz9DAwMEdKO
oSEBPn5BhgzhjiEGQOBoEBQWacCABRhAAS65cNeQgACQ+Z7uQJ6hiQJegGyOi1NUqJsT2BwTbKYP
OgAOX9avD7FKMiGHPpZABQY3TNbH1S3I2YmAZX5+BkYKzgpM6G6A2p8CSQMO34FsFkgasGtgQE8D
kxFpwM3HKMDbD9koaBowQqSBSANHM2xuITINePuBVRlakJAGfKNCA4d3GkAKVGqnAQAAAAD//w==



数据解压缩后,用base64编码的代码如下:

Data after decompression, encoded with base64 look like this:

root@localhost:~# zlib-flate -uncompress < ./dbgZlib | base64
AAYCJlMAAAACAgIsAAAuJwAAAAMDnRBoAAAAbgAAAAEAAAAAAAAAAAAAAPMBkjIwMTUxMTE5UkNU
TFBHTjAwMQAAAAAAAAAAAABBVVRQTE5SMQBXQVQwMDAwQTBSVlkwAAAAAAAAAAAAAAAAAAAAAAAA
AAAwMDAwMDAwMAAAAAAAAAAAAAAAAAAAAAAAAAAAMDAwMFdFVFBQTFBHTklHMDAwMTQgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAwMAAAAAAAAAAAAABEQlpVRkIAAAAAMDQAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAX14QAAAAAAAAAA
AAAAAAAAAAAAAAAAAAIBAAAAAAAAAAAAAABBVDAwMDBBMFJWWTAAAAAAAAAAUExOAAAAAAAAAABM
RUZSQ0IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATk4wMiBDIAIAAAAAAAAAAAAAAAAA
AAABBfXhAAAAAGQCAgIsAABA9wAAAAQDnRBoAAA+gAAAAAEAAAAAAAAAAAAAAPMBkzIwMTUxMTE5
UkNGTDJQS04AAAAAAAAAAAAAAABBVVRQTE5SMgBXQVQwMDAwQTBZMEE2AAAAAAAAAAAAAAAAAAAA
AAAAAAAwMDAwMDAwMAAAAAAAAAAAAAAAAAAAAAAAAAAAMDAwMFdFVFBQTFBLTjAwMDAwMTggICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAwMAAAAAAAAAAAAABETVpVUUIAAAAAMDQAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAX14QAAAAAA
AAAAAAAAAAAAAAAAAAAAAAIBAAAAAAAAAAAAAABBVDAwMDBBMFkwQTYAAAAAAAAAUExOAAAAAAAA
AABMRUZSQ0IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATk4wMiBDIAIAAAAAAAAAAAAA
AAAAAAABBfXhAAAAAGQ=


推荐答案

问题是您将 zlib-flate 用作通用压缩根据的算法,不应这样做:

The problem is that you are using zlib-flate as a general-purpose compression algorithm which, according to the manpage for it, you should not do:

所以也许您应该遵循工具给出的说明,而不要使用他们为他们不想要的东西。使用 gzip System.IO.Compression.GZipStream 代替,它要简单得多,尤其是在您要查找的时候跨平台兼容的压缩算法。

So perhaps you should follow the instructions given by your tools and not use them for things that they are not intended for. Use gzip and the System.IO.Compression.GZipStream instead, it's much simpler, especially when you're looking for cross-platform compatible compression algorithms.

这就是说...

不能膨胀的原因数据是它缺少正确的GZIP标头。如果在其中添加了正确的标题,则会得到可以解压缩的内容。

The reason that you can't inflate the data is that it lacks a correct GZIP header. If you add the right header to it you will get something that can be decompressed.

例如:

public static byte[] DecompressZLibRaw(byte[] bCompressed)
{
    byte[] bHdr = new byte[] { 0x1F, 0x8b, 0x08, 0, 0, 0, 0, 0 };

    using (var sOutput = new MemoryStream())
    using (var sCompressed = new MemoryStream())
    {
        sCompressed.Write(bHdr, 0, bHdr.Length);
        sCompressed.Write(bCompressed, 0, bCompressed.Length);
        sCompressed.Position = 0;
        using (var decomp = new GZipStream(sCompressed, CompressionMode.Decompress))
        {
            decomp.CopyTo(sOutput);
        }
        return sOutput.ToArray();
    }
}

添加标头会带来很大的不同。

Adding the header makes all the difference.

NB:10字节GZIP标头中有两个字节没有从源中剥离。这些通常用于存储压缩标志和源文件系统。在您提供的压缩数据中,它们是无效值。此外,文件页脚缩写为5个字节,而不是8个字节...实际上,解压缩实际上并不需要所有这些。可能与手册页上的内容为何不将其用于一般压缩有很大关系。

NB: There are two bytes in the 10-byte GZIP header that are not stripped from your source. These are normally used to store the compression flags and the source file system. In the compressed data you present they are invalid values. Additionally the file footer is abbreviated to 5 bytes instead of 8 bytes... all of which is not actually required for decompression. Which probably has a lot to do with why the manpage says not to use this for general compression.

这篇关于Zlib压缩不兼容C与C#的实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-03 19:22