在C#中解压缩流

时间:2011-11-21 13:21:58

标签: c# .net zip

我正在使用C#,我正在为互联网下载一个包含一个XML文件的zip文件。我希望加载这个XML文件。这就是我到目前为止所做的:

byte[] data;
WebClient webClient = new WebClient();
try {
    data = webClient.DownloadData(downloadUrl);
}
catch (Exception ex) {
    Console.WriteLine("Error in DownloadData (Ex:{0})", ex.Message);
    throw;
}

if (data == null) {
    Console.WriteLine("Bulk data is null");
    throw new Exception("Bulk data is null");
}

//Create the stream
MemoryStream stream = new MemoryStream(data);
XmlDocument document = new XmlDocument();

//Gzip
GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress);

//Load report straight from the gzip stream
try {
    document.Load(gzipStream);
}
catch (Exception ex) {
    Console.WriteLine("Error in Load (Ex:{0})", ex.Message);
    throw;
}
document.Load中的

我总是得到以下例外:
GZip标头中的幻数不正确。确保传入GZip流。

我做错了什么?

5 个答案:

答案 0 :(得分:5)

我使用的是SharpZipLib,效果很好!

下面是一个封装库

的函数
 public static void Compress(FileInfo sourceFile, string destinationFileName,string destinationTempFileName)
        {
            Crc32 crc = new Crc32();
            string zipFile = Path.Combine(sourceFile.Directory.FullName, destinationTempFileName);
            zipFile = Path.ChangeExtension(zipFile, ZIP_EXTENSION);

            using (FileStream fs = File.Create(zipFile))
            {
                using (ZipOutputStream zOut = new ZipOutputStream(fs))
                {
                    zOut.SetLevel(9);
                    ZipEntry entry = new ZipEntry(ZipEntry.CleanName(destinationFileName));

                    entry.DateTime = DateTime.Now;
                    entry.ZipFileIndex = 1;
                    entry.Size = sourceFile.Length;

                    using (FileStream sourceStream = sourceFile.OpenRead())
                    {
                        crc.Reset();
                        long len = sourceFile.Length;
                        byte[] buffer = new byte[bufferSize];
                        while (len > 0)
                        {
                            int readSoFar = sourceStream.Read(buffer, 0, buffer.Length);
                            crc.Update(buffer, 0, readSoFar);
                            len -= readSoFar;
                        }
                        entry.Crc = crc.Value;
                        zOut.PutNextEntry(entry);

                        len = sourceStream.Length;
                        sourceStream.Seek(0, SeekOrigin.Begin);
                        while (len > 0)
                        {
                            int readSoFar = sourceStream.Read(buffer, 0, buffer.Length);
                            zOut.Write(buffer, 0, readSoFar);
                            len -= readSoFar;
                        }
                    }
                    zOut.Finish();
                    zOut.Close();
                }
                fs.Close();
            }
        }

答案 1 :(得分:5)

显然SharpZipLib现在没有维护,你可能想避免它: https://stackoverflow.com/a/593030

在.NET 4.5中,现在有built in support for zip files,因此对于您的示例,它将是:

var data = new WebClient().DownloadData(downloadUrl);

//Create the stream
var stream = new MemoryStream(data);

var document = new XmlDocument();

//zip
var zipArchive = new ZipArchive(stream);

//Load report straight from the zip stream
document.Load(zipArchive.Entries[0].Open());

答案 2 :(得分:4)

如果您的字节数组包含带有单个文件的zip存档,则可以使用ZipArchive类获取带有文件数据的解压缩字节数组。 ZipArchive包含在.NET 4.5中,在程序集System.IO.Compression.FileSystem中(您需要显式引用它)。

以下功能改编自this answer,对我有用:

public static byte[] UnzipSingleEntry(byte[] zipped)
{
    using (var memoryStream = new MemoryStream(zipped))
    {
        using (var archive = new ZipArchive(memoryStream))
        {
            foreach (ZipArchiveEntry entry in archive.Entries)
            {
                using (var entryStream = entry.Open())
                {
                    using (var reader = new BinaryReader(entryStream))
                    {
                        return reader.ReadBytes((int)entry.Length);
                    }
                }
            }
        }
    }
    return null; // To quiet my compiler
}

答案 3 :(得分:2)

正如其他人提到的那样,GZip和Zip不一样,所以你可能需要使用一个zip库。我使用名为:DotNetZip的库 - 可从以下网站获得:

http://dotnetzip.codeplex.com/

答案 4 :(得分:1)

来自GZipStream Class说明:

  

写入扩展名为.gz的文件的压缩GZipStream对象可以使用许多常用的压缩工具解压缩;但是,此类本身并不提供向.zip存档添加文件或从中提取文件的功能

因此,除非您控制服务器端文件,否则我建议您查找特定的zip目标库(例如SharpZipLib)。