.Net zlib inflate with .Net 4.5

人盡茶涼 提交于 2019-12-17 20:23:13

问题


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.


回答1:


What are the first several bytes of the data you are trying to compress?

You might have zlib, gzip, or raw deflate data that you're trying to decode.

By the way, I highly recommend that you use DotNetZip's interface to zlib instead of NET 4.5's (or NET any version). NET 4.5 has bugs in that interface that Microsoft has declared that they won't fix (!).




回答2:


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?




回答3:


Here's a revised version of ProVega's answer, which inflates the byte array into a string:

using (var stream = new MemoryStream(bytes,2, bytes.Length - 2))
using (var inflater = new DeflateStream(stream, CompressionMode.Decompress))
using (var streamReader = new StreamReader(inflater))
{
    return streamReader.ReadToEnd();
}


来源:https://stackoverflow.com/questions/17212964/net-zlib-inflate-with-net-4-5

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!