views:

613

answers:

3

Hello.. I am trying to decompress a (.gz) file using the GZipStream class that is included in the .NET framework. I am using the MSDN documentation and I keep getting this exception: "Writing to the compression stream is not supported."

Here is the application source:

 try
            {

                var infile = new FileStream(@"C:\TarDecomp\TarDecomp\TarDecomp\bin\Debug\nick_blah-2008.tar.gz", FileMode.Open, FileAccess.Read, FileShare.Read);
                byte[] buffer = new byte[infile.Length];
                // Read the file to ensure it is readable.
                int count = infile.Read(buffer, 0, buffer.Length);
                if (count != buffer.Length)
                {
                    infile.Close();
                    Console.WriteLine("Test Failed: Unable to read data from file");
                    return;
                }
                infile.Close();
                MemoryStream ms = new MemoryStream();
                // Use the newly created memory stream for the compressed data.
                GZipStream compressedzipStream = new GZipStream(ms, CompressionMode.Decompress, true);
                Console.WriteLine("Decompression");
                compressedzipStream.Write(buffer, 0, buffer.Length);
                // Close the stream.
                compressedzipStream.Close();
                Console.WriteLine("Original size: {0}, Compressed size: {1}", buffer.Length, ms.Length);

The exception is thrown at the compressedZipStream.write().

Any ideas? What is this exception telling me? Thanks!

+5  A: 

It is telling you that you should call Read instead of Write since it's decompression! Also the memory stream should be constructed with the data, or rather you should pass the file stream directly to the GZipStream constructor.

Example of how it should have been done (haven't tried to compile it):

Stream inFile = new FileStream(@"C:\TarDecomp\TarDecomp\TarDecomp\bin\Debug\nick_blah-2008.tar.gz", FileMode.Open, FileAccess.Read, FileShare.Read);
Stream decodedStream = new MemoryStream();
byte[] buffer = new byte[4096];

using (Stream inGzipStream = new GZipStream(inFile, CompressionMode.Decompress))
{
    int bytesRead;
    while ((bytesRead = inGzipStream.Read(buffer, 0, buffer.Length)) > 0)
        decodedStream.Write(buffer, 0, bytesRead);
}

// Now decodedStream contains the decoded data
Filip Navara
I'm trying this thank you.
Nick
Your the man.. Thanks!
Nick
Glad to help. :)
Filip Navara
A: 

How compression streams work can be puzzling at first.

Reading takes compressed data and writing takes uncompressed data. All in all, the stream ensures you only "see" uncompressed data at all times.

The proper way to achieve what you are trying to do, is to read using the GZipStream and then write using the GZipStream also.

Bryan Menard
+2  A: 

The compression code doesn't work like encryption - you can't decompress from one stream to another by writing the compressed data. You have to provide a stream which contains the compressed data already and let GZipStream read from it. Something like this:

using (Stream file = File.OpenRead(filename))
using (Stream gzip = new GZipStream(file, CompressionMode.Decompress))
using (Stream memoryStream = new MemoryStream())
{
   CopyStream(gzip, memoryStream);
   return memoryStream.ToArray();
}

CopyStream is a simple utility method to read from one stream and copy all the data to another. Something like this:

static void CopyStream(Stream input, Stream output)
{
    byte[] buffer = new byte[8192];
    int bytesRead;
    while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0)
    {
        output.Write(buffer, 0, bytesRead);
    }
}
Jon Skeet