在C#中解压缩流

13

我正在使用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流。

我做错了什么?


2
你是在下载 GZip 还是 Zip?这两者并不相同。 - Oded
zip != gzip - 请参阅http://en.wikipedia.org/wiki/Gzip和http://en.wikipedia.org/wiki/ZIP_%28file_format%29。 - Polynomial
我想这是我的第一个错误。它是一个 ZIP 文件而不是 Gzip。 - Roee Gavirel
5个回答

12

显然SharpZipLib现在没有维护,你可能想要避免使用它: https://dev59.com/q3RB5IYBdhLWcg3wiHv7#593030

在.NET 4.5中,现在有内置支持zip文件的功能, 因此对于您的示例,可以这样:

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

如果您需要支持其他未受支持的压缩格式,例如支持.NET Core和NETFX的tgz,请尝试使用https://github.com/adamhathcock/sharpcompress。 - Michael

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

下面的函数是从这个回答进行了改编,适用于我:

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
}

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

2

正如其他人所提到的,GZip和Zip不同,因此您可能需要使用一个zip库。我使用一个叫做DotNetZip的库 - 可从以下网站下载:

http://dotnetzip.codeplex.com/


1

GZipStream Class 的描述中得知:

使用扩展名为 .gz 的文件写入的压缩 GZipStream 对象可以使用许多常见的压缩工具进行解压缩;但是,这个类本身并没有为添加文件到或从 .zip 存档中提供功能。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接