2011-11-21 117 views
6

我正在C#中工作,并且正在为互联网下载一个带有一个XML文件的zip文件。我希望加载这个XML文件。这是我到目前为止有:在C中解压缩流#

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流。

我在做什么错了?

+1

你下载一个'GZip'或'Zip'?两者不一样。 – Oded

+0

'zip!= gzip' - 见http://en.wikipedia.org/wiki/Gzip和http://en.wikipedia.org/wiki/ZIP_%28file_format%29 – Polynomial

+0

我想这是我的第一个错误。这是一个不是Gzip的zip文件。 –

回答

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

GZipStream Class描述的功能:可以使用多种常用的压缩工具进行解压缩

写入到文件以.gz的扩展名的压缩GZipStream对象;然而,这个类本身并没有从.zip文件

将文件添加或提取文件,因此,除非你控制的服务器端文件,我建议寻找特定的拉链针对性库(SharpZipLib例如提供功能)。

2

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

http://dotnetzip.codeplex.com/

4

显然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()); 
3

如果您有一个包含一个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 
}