Search code examples
.netinflatedeflatedeflatestream

.NET DeflateStream Usage


I am trying to utilize the INFLATE compression stream in .NET using a DeflateStream. My code throws an InvalidDataException although I know that the data I am passing has been correctly processed by the DEFLATE algorithm (it has been tested). Am I using the DeflateStream incorrectly? My code is as follows:

public byte[] Inflate(byte[] deflateArr)
    {
        MemoryStream ms;

        // try to create a MemoryStream from a byte array
        try
        {
            ms = new MemoryStream(deflateArr);
        }
        catch (ArgumentNullException)
        {
            return null;
        }

        // create a deflatestream and pass it the memory stream
        DeflateStream ds;
        try
        {
            ds = new DeflateStream(ms, CompressionMode.Decompress);
        }
        catch (ArgumentNullException)
        {
            return null;
        }
        catch (ArgumentException)
        {
            return null;
        }

        // create a bytes array and read into it
        byte[] bytes = new byte[4096];

        try
        {
            ds.Read(bytes, 0, 4096);
        }
        catch (ArgumentNullException)
        {
            return null;
        }
        catch (InvalidOperationException)
        {
            return null;
        }
        catch (ArgumentOutOfRangeException)
        {
            return null;
        }
        catch (InvalidDataException)
        {
            return null;
        }

        // close the memory stream
        ms.Close();

        // close the deflate stream
        ds.Close();

        return bytes;
    }

Solution

  • No, you're not.

    Things wrong with this code:

    • Explicitly calling Close() instead of using a using statement. Probably not harmful here, but a bad idea.
    • Catching various exceptions which you really shouldn't be catching at all, as they indicate programming bugs
    • Catching exceptions on a per-statement basis, even though you're treating them the same way throughout the code (so could catch the exceptions for a much larger block)
    • Ignoring the return value of Stream.Read

    Here's a better version, assuming you're using .NET 4 (for Stream.CopyTo)

    public static byte[] Inflate(byte[] inputData)
    {
        using (Stream input = new DeflateStream(new MemoryStream(inputData),
                                                CompressionMode.Decompress))
        {
            using (MemoryStream output = new MemoryStream())
            {
                input.CopyTo(output);
                return output.ToArray();
            }
        }
    }
    

    Now you may want to catch InvalidDataException - personally I wouldn't at this point, but it may make sense to do so. (I'd catch it at the calling side, if necessary. You can always wrap this method in another one if necessary.)