开发者

Programmatic compression/decompression to MemoryStream with GZipStream

I built (based on a CodeProject article) a wrapper class (C#) to use a GZipStream to compress a MemoryStream. It compresses fine but doesn't decompress. I've looked at many other examples that have the same problem, and I feel like I'm following what's said but still am getting nothing when I decompress. Here's the compression and decompression methods:

public static byte[] Compress(byte[] bSource)
{

    using (MemoryStream ms = new MemoryStream())
    {
        using (GZipStream gzip = new GZipStream(ms, CompressionMode.Compress, true))
        {
            gzip.Write(bSource, 0, bSource.Length);
            gzip.Close();
        }

        return ms.ToArray();
    }
}


public static byte[] Decompress(byte[] bSource)
{

    try
    {
        using (MemoryStream ms = new M开发者_C百科emoryStream())
        {
            using (GZipStream gzip = new GZipStream(ms, CompressionMode.Decompress, true))
            {
                gzip.Read(bSource, 0, bSource.Length);
                gzip.Close();
            }

            return ms.ToArray();
        }
    }
    catch (Exception ex)
    {
        throw new Exception("Error decompressing byte array", ex);
    }
}

Here's an example of how I use it:

string sCompressed = Convert.ToBase64String(CompressionHelper.Compress("Some Text"));
// Other Processes
byte[] bReturned = CompressionHelper.Decompress(Convert.FromBase64String(sCompressed));
// bReturned has no elements after this line is executed


There is a bug in Decompress method.

The code does not read content of bSource. On the contrary, it overrides its content wile reading from empty gzip, created based on empty memory stream.

Basically what your version of code is doing:

//create empty memory
using (MemoryStream ms = new MemoryStream())

//create gzip stream over empty memory stream
using (GZipStream gzip = new GZipStream(ms, CompressionMode.Compress, true))

// write from empty stream to bSource
gzip.Write(bSource, 0, bSource.Length);

The fix could look like this:

public static byte[] Decompress(byte[] bSource)
{
    using (var inStream = new MemoryStream(bSource))
    using (var gzip = new GZipStream(inStream, CompressionMode.Decompress))
    using (var outStream = new MemoryStream())
    {
        gzip.CopyTo(outStream);
        return outStream.ToArray();
    }
}


The OP said in an edit, now rolled back:

Thanks to Alex's explanation of what was going wrong, I was able to fix the Decompress method. Unfortunately, I'm using .Net 3.5, so I wasn't able to implement the Stream.CopyTo method he suggested. With his explanation, though, I was able to figure out a solution. I made the appropriate changes to the Decompress method below.

    public static byte[] Decompress(byte[] bSource)
    {
        try
        {
            using (var instream = new MemoryStream(bSource))
            {
                using (var gzip = new GZipStream(instream, CompressionMode.Decompress))
                {
                    using (var outstream = new MemoryStream())
                    {
                        byte[] buffer = new byte[4096];

                        while (true)
                        {
                            int delta = gzip.Read(buffer, 0, buffer.Length);

                            if (delta > 0)
                                outstream.Write(buffer, 0, delta);

                            if (delta < 4096)
                                break;
                        }
                        return outstream.ToArray();
                    }
                }
            }
        }
        catch (Exception ex)
        {
            throw new Exception("Error decompressing byte array", ex);
        }
    }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜