ZlibException "inflating: " When Closing or Disposing DeflateStream

Sep 28, 2009 at 7:12 PM


I am attempting to compress and decompress some byte arrays using version 1.9 of the libraries.  Everything goes as expected, but sometimes I get a ZlibException "inflating:" from the library.  Unfortunately, it isn't every time, just sometimes.  This occurs when I am attempting to Close() or Dispose() of the DeflateStream after everything has worked out correctly.  My code is as follows:

                int compressedLength;
                byte[] bufferedBytes;

                MemoryStream memoryStream = new MemoryStream();
                DeflateStream deflateStream = new DeflateStream(memoryStream, CompressionMode.Decompress, false);

                bufferedBytes = new byte[buffer.Count];
                Array.Copy(buffer.Array, buffer.Offset, bufferedBytes, 0, buffer.Count);
                deflateStream.Write(bufferedBytes, 0, bufferedBytes.Length);

                compressedLength = (int)memoryStream.Length;
                bufferedBytes = bufferManager.TakeBuffer(compressedLength + buffer.Offset);
                Array.Copy(buffer.Array, 0, bufferedBytes, 0, buffer.Offset);
                Array.Copy(memoryStream.ToArray(), 0, bufferedBytes, buffer.Offset, compressedLength);



The exception detail is as follows:

Ionic.Zlib.ZlibException was unhandled by user code
  Message="inflating: "
       at Ionic.Zlib.ZlibBaseStream.finish()
       at Ionic.Zlib.ZlibBaseStream.Close()
       at Ionic.Zlib.DeflateStream.Dispose(Boolean disposing)
       at System.IO.Stream.Close()
       at PCAPPS.DataServices.WCF.DataService.DeflateMessageEncoderFactory.DeflateMessageEncoder.DecompressBuffer_Ionic(ArraySegment`1 buffer, BufferManager bufferManager) in C:\Documents and Settings\dvajda\My Documents\Visual Studio 2008\Projects\WCF\WCF.DataContracts\DeflateMessageEncoderFactory.cs:line 230
       at PCAPPS.DataServices.WCF.DataService.DeflateMessageEncoderFactory.DeflateMessageEncoder.ReadMessage(ArraySegment`1 buffer, BufferManager bufferManager, String contentType) in C:\Documents and Settings\dvajda\My Documents\Visual Studio 2008\Projects\WCF\WCF.DataContracts\DeflateMessageEncoderFactory.cs:line 52
       at System.ServiceModel.Channels.HttpInput.DecodeBufferedMessage(ArraySegment`1 buffer, Stream inputStream)
       at System.ServiceModel.Channels.HttpInput.ReadBufferedMessage(Stream inputStream)
       at System.ServiceModel.Channels.HttpInput.ParseIncomingMessage(Exception& requestException)
       at System.ServiceModel.Channels.HttpRequestContext.CreateMessage()
       at System.ServiceModel.Channels.HttpChannelListener.HttpContextReceived(HttpRequestContext context, ItemDequeuedCallback callback)

I do not get this exception every time, just SOMETIMES, which is really annoying.  But it consistently happens if I run the code in a loop, or if I just keep trying it.  I have found a workaround which basically uses DeflateStream.Read() instead of DeflateStream.Write(), but I would really like to use the DeflateStream.Write() method (also, the Read() seems to have a bug in it as well, but I have another posting on this forum about that).  My workaround code is as follows:

                int compressedLength;
                byte[] bufferedBytes;

                MemoryStream memoryStream = new MemoryStream(buffer.Array, buffer.Offset, buffer.Count);
                DeflateStream deflateStream = new DeflateStream(memoryStream, CompressionMode.Decompress, true);
                MemoryStream uncompressedStream = new MemoryStream();
                int readBytes = 0;
                bufferedBytes = new byte[Math.Min(1024, buffer.Count)];
                while ((readBytes = deflateStream.Read(bufferedBytes, 0, bufferedBytes.Length)) > 0)
                    uncompressedStream.Write(bufferedBytes, 0, readBytes);

Any input as to how I can avoid the "inflating:" exception would be much appreciated, as I would really like to use the first code format (involving Write()) for efficiency in my code.

Sep 28, 2009 at 7:36 PM

I delved into the source code for the ZlibBaseStream, and I think I found the issue.  In my code, I am attempting to decompress, but the error says "inflating: "...  Looking at the internal private members and variables of my DeflateStream during the exception, I can see that the base stream of my DeflateStream has _wantCompress set to false, which is correct.  But the source code for ZlibBaseStream in the finish() function looks as follows:

                    int rc = (_wantCompress)
                        ? _z.Deflate(FlushType.Finish)
                        : _z.Inflate(FlushType.Finish);

                    if (rc != ZlibConstants.Z_STREAM_END && rc != ZlibConstants.Z_OK)
                        throw new ZlibException((_wantCompress ? "de" : "in") + "flating: " + _z.Message);

This seems incorrect to me.  If _wantCompress is false, as it should be, then it seems like the shorthand if statements are backwards, ie, I would want to call _z.Deflate(FlushType.Finish) and the error should at least say "deflating: " not "inflating: ".  Any thoughts, it just seems like the two if statements are backwards.  I think the first one causes rc to be incorrectly set, which then causes exception to be thrown.

Or I'm just way off.


Sep 29, 2009 at 7:41 AM
This discussion has been copied to a work item. Click here to go to the work item and continue the discussion.
Sep 29, 2009 at 12:27 PM

This is a bug in DotNetZip.

It's been fixed in changeset 44267.  First binary with the fix is, will be available soon.

I don't know what you are trying to say with your second mail.  Your application used the DeflateStream in Decompress mode, which means Inflate.  The problem you had was during inflation.  The logic in that code you cited is correct.