我正在使用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流。
我做错了什么?
答案 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的库 - 可从以下网站获得:
答案 4 :(得分:1)
来自GZipStream Class说明:
写入扩展名为.gz的文件的压缩GZipStream对象可以使用许多常用的压缩工具解压缩;但是,此类本身并不提供向.zip存档添加文件或从中提取文件的功能
因此,除非您控制服务器端文件,否则我建议您查找特定的zip目标库(例如SharpZipLib)。