Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
412 views
in Technique[技术] by (71.8m points)

c# - .Net zlib inflate with .Net 4.5

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

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

1 Reply

0 votes
by (71.8m points)

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?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...