Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

According to MSDN in .Net 4.5 System.IO.Compression is based on zlib.
I am trying now to change my current interop based reading from a zlib deflated stream from a non .NET server into a BCL based implementation.
My implementation looks like this:

    var enc = new UTF8Encoding();            
        var readBytes = BufferSizeRaw;
        var outputBuffer = new byte[BufferSizeRaw];            
        var networkBuffer = _networkQueue.Take();
        var ms = new MemoryStream(networkBuffer.InputBuffer, 0, networkBuffer.UsedLength);
        using (Stream stream = new DeflateStream(ms, CompressionMode.Decompress))
            while (readBytes==BufferSizeRaw)
            {
                readBytes = stream.Read(outputBuffer, 0, outputBuffer.Length);                
                stringBuffer+= enc.GetString(outputBuffer, 0, readBytes);                
            }

I receive the following exception on the first call of the decompression/read on the DeflateStream :

Block length does not match with its complement

The interop based call uses var result=inflate(ref zStyream, ZLibFlush.NoFlush;
Has anyone tried the same or sees a reason for an error in the code or is there a wrong understanding on my end? I have also tried it with truncating the first two bytes without any luck.
The first few bytes are 20, 202, 177,13.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
400 views
Welcome To Ask or Share your Answers For Others

1 Answer

The answer above is correct but isn't exactly clear on the "why". The first two bytes of a raw ZLib stream provide details about the type of compression used. Microsoft's DeflateStream class in System.Io.Compression doesn't understand these. The fix is as follows:

using (MemoryStream ms = new MemoryStream(data))
{
    MemoryStream msInner = new MemoryStream();

    // Read past the first two bytes of the zlib header
    ms.Seek(2, SeekOrigin.Begin);

    using (DeflateStream z = new DeflateStream(ms, CompressionMode.Decompress))
    {
        z.CopyTo(msInner);

In this example, data is a Byte[] with the raw Zlib file. After loading it into a MemoryStream, we simply "seek" past the first two bytes.

The post explains what a Zlib header looks like if you are looking at the raw bytes.

What does a zlib header look like?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...