在C#中解压缩.gz流

时间:2015-12-30 15:06:23

标签: c# xml stream gz

很抱歉,如果这是一个菜鸟问题,那是我第一次使用C#。

此代码的目的是检索.gz文件,对其进行解压缩并将内容推送到一个字符串中,然后我可以使用该字符串来编组内部的XML。

从服务器请求特定的.gz文件后,我将结果发送到Stream中,如下所示:

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

但是,我找不到任何关于如何解压缩Stream中的.gz的答案,只能找到如何从文件中解压缩。所以我使用以下方法将传入的.gz保存到本地文件中:

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

然后尝试使用以下方法解压缩新创建的文件:

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);
        }
    }
}

目的是创建一个XML文件,然后可以调用该文件将节点封送到一个对象中。当我运行它时,我得到:

System.dll

中出现'System.IO.InvalidDataException'类型的未处理异常
  

附加信息:GZip标头中的幻数不是   正确。确保传入GZip流。

我的问题是我是否遵循了正确的流程,即将.gz文件保存在Stream中,保存它,调用新保存的.gz文件进行解压缩并保存到XML文件,调用新的.xml文件然后整理它。如果是的话,我在这里做错了什么。如果没有,有没有办法在gz中获取XML而无需创建和加载新文件?

2 个答案:

答案 0 :(得分:1)

此异常正在抛出,因为您尝试使用GZipStream解压缩的Stream不是有效的GZip,您可以使用以下代码重现此异常:

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);
}

输出

  

GZip标头中的幻数不正确。确保传入GZip流。

因此,您必须确保从WebRequest中获取GZIP流,

您也可以简化代码,如下所示:

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);

答案 1 :(得分:0)

最后,我设法通过将.gz流保存到文件中,然后读取这些文件来解压缩xml,然后保存xml文件。再往下,当数据已经编组时,消除文件以避免浪费空间。

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);
                }
            }
        }
    }
}

我希望这可以帮助其他任何人解决这个问题。

相关问题