Asinus Rex
Asinus Rex

Reputation: 554

Decompress .gz Stream in C#

Sorry if this is a noob question, it's my first time using C#.

The purpose of this code is to retrieve a .gz file, decompress it and push the content into a string I can then use to marshal the XML inside.

After requesting a specific .gz file from the server, I am sending the results into a Stream, like so:

HttpWebResponse OauthResponse = (HttpWebResponse)OauthRequest.GetResponse();
Stream stream = OauthResponse.GetResponseStream();

However, I cannot find any answers as to how to decompress the .gz in the Stream, only how to do so from a file. So I'm saving the incoming .gz into a local file using this:

using (StreamReader sr = new StreamReader(stream))
{
    using (BinaryWriter writer = new BinaryWriter(File.Open("currentSession.gz", FileMode.Create)))
    {
        writer.Write(sr.ReadToEnd());
    }
}

And then trying to decompress the newly created file with this:

using (GZipStream instream = new GZipStream(File.OpenRead("currentSession.gz"), CompressionMode.Decompress))
{
    using (FileStream outputStream = new FileStream("currentXML.xml", FileMode.Append, FileAccess.Write))
    {
        int bufferSize = 8192, bytesRead = 0;
        byte[] buffer = new byte[bufferSize];
        while ((bytesRead = instream.Read(buffer, 0, bufferSize)) > 0)
        {
            outputStream.Write(buffer, 0, bytesRead);
        }
    }
}

The intention is that it would create an XML file that can then be called to marshal the nodes into an object. When I run it though, I get:

An unhandled exception of type 'System.IO.InvalidDataException' occurred in System.dll

Additional information: The magic number in GZip header is not correct. Make sure you are passing in a GZip stream.

My question is whether I'm following the right process, ie, getting the .gz file in a Stream, saving it, calling the newly saved .gz file to decompress and save to an XML file, call the new .xml and then marshal it. If it is, what am I doing wrong here. If not, is there a way of getting the XML inside the gz without the need to create and load the new files?

Upvotes: 1

Views: 2022

Answers (2)

Asinus Rex
Asinus Rex

Reputation: 554

In the end I managed to make it work by saving the .gz stream into files, then reading those files to decompress the xml, then saving the xml files. Further down, when the data is already marshalled, eliminate the files to avoid wasting space.

public static void saveDecompress(Stream LPDataStream, int c)
{
    //Save the incoming .gz in a file
    using (FileStream output = File.OpenWrite("temp/session" + c + ".gz"))
    {
        LPDataStream.CopyTo(output);
    }

    DirectoryInfo directorySelected = new DirectoryInfo("temp/");
    //Iterate through the .gz files to extract xml
    foreach (FileInfo fileToDecompress in directorySelected.GetFiles("*.gz"))
    {
        using (FileStream originalFileStream = fileToDecompress.OpenRead())
        {
            string currentFileName = fileToDecompress.FullName;
            string newFileName = currentFileName.Remove(currentFileName.Length - fileToDecompress.Extension.Length) + ".xml";

            //Save XML in file
            using (FileStream decompressedFileStream = File.Create(newFileName))
            {
                using (GZipStream decompressionStream = new GZipStream(originalFileStream, CompressionMode.Decompress))
                {
                    decompressionStream.CopyTo(decompressedFileStream);
                }
            }
        }
    }
}

I hope this helps anyone else with the issue.

Upvotes: 0

Alberto Monteiro
Alberto Monteiro

Reputation: 6219

This exception is throwing because the Stream that you are trying to decompress with GZipStream isnt a valid GZip, you can reproduce this exception using this code:

Stream stream = new MemoryStream(Encoding.UTF8.GetBytes("Hellow"));

try
{
    using (var instream = new GZipStream(stream, CompressionMode.Decompress))
    using (var outputStream = new FileStream("currentXML.xml", FileMode.Append, FileAccess.Write))
    {
        instream.CopyTo(outputStream);
    }
}
catch (Exception e)
{
    Console.WriteLine(e.Message);
}

Output

The magic number in GZip header is not correct. Make sure you are passing in a GZip stream.

So you must assure that you are reiving a GZIP stream from your WebRequest,

You also can simplify you code, like this:

HttpWebResponse OauthResponse = (HttpWebResponse)OauthRequest.GetResponse();
Stream stream = OauthResponse.GetResponseStream();
using (var instream = new GZipStream(stream, CompressionMode.Decompress))
using (var outputStream = new FileStream("currentXML.xml", FileMode.Append, FileAccess.Write))
    instream.CopyTo(outputStream);

Upvotes: 1

Related Questions