Search code examples
c#monodeflatestream

Can't inflate with C# using DeflateStream


I'm using mono to inflate/deflate bytes. Here is the code:

public static byte[] Inflate(byte[] data)
    {
        using (MemoryStream inStream = new MemoryStream(data))
        {
            using (MemoryStream outStream = new MemoryStream())
            {
                using (DeflateStream decompressStream = new DeflateStream(inStream, CompressionMode.Decompress))
                {
                    decompressStream.CopyTo(outStream);
                }
                return outStream.ToArray();
            }
        }
    }

The input data is : <789c3dca b9110020 0c04b196 bc9c3f7a 73f11030 281652d1 88b04195 1e742987 2f86258f acdec63d 6dcf0184 560cde> 47bytes. The algorithm is DEFLATE.

I've successfully inflate the same data on other platform, but through the code above, it throws the following exception:

System.IO.IOException: Corrupted data ReadInternal
  at System.IO.Compression.DeflateStreamNative.CheckResult (Int32 result, System.String where) [0x00000] in <filename unknown>:0 
  at System.IO.Compression.DeflateStreamNative.ReadZStream (IntPtr buffer, Int32 length) [0x00000] in <filename unknown>:0 
  at System.IO.Compression.DeflateStream.ReadInternal (System.Byte[] array, Int32 offset, Int32 count) [0x00000] in <filename unknown>:0 
  at System.IO.Compression.DeflateStream.Read (System.Byte[] dest, Int32 dest_offset, Int32 count) [0x00000] in <filename unknown>:0 
  at System.IO.Stream.CopyTo (System.IO.Stream destination, Int32 bufferSize) [0x00000] in <filename unknown>:0 
  at System.IO.Stream.CopyTo (System.IO.Stream destination) [0x00000] in <filename unknown>:0 

Solution

  • Finally I used DotNetZip: http://dotnetzip.codeplex.com to solve the problem.

    public static byte[] Inflate(byte[] data)
        {
            int outputSize = 1024;
            byte[] output = new Byte[ outputSize ];
            bool expectRfc1950Header = true;
            using ( MemoryStream ms = new MemoryStream())
            {
                ZlibCodec compressor = new ZlibCodec();
                compressor.InitializeInflate(expectRfc1950Header);
    
                compressor.InputBuffer = data;
                compressor.AvailableBytesIn = data.Length;
                compressor.NextIn = 0;
                compressor.OutputBuffer = output;
    
                foreach (var f in new FlushType[] { FlushType.None, FlushType.Finish } )
                {
                    int bytesToWrite = 0;
                    do
                    {
                        compressor.AvailableBytesOut = outputSize;
                        compressor.NextOut = 0;
                        compressor.Inflate(f);
    
                        bytesToWrite = outputSize - compressor.AvailableBytesOut ;
                        if (bytesToWrite > 0)
                            ms.Write(output, 0, bytesToWrite);
                    }
                    while (( f == FlushType.None && (compressor.AvailableBytesIn != 0 || compressor.AvailableBytesOut == 0)) ||
                        ( f == FlushType.Finish && bytesToWrite != 0));
                }
    
                compressor.EndInflate();
    
                return ms.ToArray();
            }
        }
    
        public static byte[] Deflate(byte[] data)
        {
            int outputSize = 1024;
            byte[] output = new Byte[ outputSize ];
            int lengthToCompress = data.Length;
    
            // If you want a ZLIB stream, set this to true.  If you want
            // a bare DEFLATE stream, set this to false.
            bool wantRfc1950Header = true;
    
            using ( MemoryStream ms = new MemoryStream())
            {
                ZlibCodec compressor = new ZlibCodec();
                compressor.InitializeDeflate(CompressionLevel.BestCompression, wantRfc1950Header);  
    
                compressor.InputBuffer = data;
                compressor.AvailableBytesIn = lengthToCompress;
                compressor.NextIn = 0;
                compressor.OutputBuffer = output;
    
                foreach (var f in new FlushType[] { FlushType.None, FlushType.Finish } )
                {
                    int bytesToWrite = 0;
                    do
                    {
                        compressor.AvailableBytesOut = outputSize;
                        compressor.NextOut = 0;
                        compressor.Deflate(f);
    
                        bytesToWrite = outputSize - compressor.AvailableBytesOut ;
                        if (bytesToWrite > 0)
                            ms.Write(output, 0, bytesToWrite);
                    }
                    while (( f == FlushType.None && (compressor.AvailableBytesIn != 0 || compressor.AvailableBytesOut == 0)) ||
                        ( f == FlushType.Finish && bytesToWrite != 0));
                }
    
                compressor.EndDeflate();
    
                ms.Flush();
                return ms.ToArray();
            }
        }