2011-11-21 12 views
6

Sto lavorando in C# e sto scaricando per Internet un file zip contenente un file XML. e desidero caricare questo file XML. Questo è quello che ho finora:Decompressione di un flusso in 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; 
} 

in document.Load sto ottenendo sempre la seguente eccezione:
Il numero magico nell'intestazione GZip non è corretto. Assicurati di passare un flusso GZip.

Cosa sto facendo male?

+1

State scaricando un 'gzip' o un' Zip'? I due non sono la stessa cosa. – Oded

+0

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

+0

Immagino che questo sia il mio primo errore. È un file zip non Gzip. –

risposta

5

Sto usando SharpZipLib e funziona benissimo!

Qui di seguito è una funzione che incapsulano la libreria

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

Da GZipStream Class Descrizione:

oggetti compressa GZipStream scritte in un file con estensione .gz possono essere decompressi con molti strumenti comuni di compressione ; tuttavia, questa classe non intrinsecamente fornisce funzionalità per l'aggiunta di file da o estrarre file da archivi .zip

Quindi, a meno di controllare i file sul lato server, io suggerirei alla ricerca di specifici biblioteca zip mirati (ad esempio SharpZipLib).

2

Come gli altri hanno menzionato GZip e Zip non sono la stessa quindi potrebbe essere necessario utilizzare una libreria zip. Io uso una libreria chiamata: DotNetZip - disponibile sul sito qui sotto:

http://dotnetzip.codeplex.com/

4

Apparentemente SharpZipLib è ora non mantenuto e probabilmente vuole evitare di usarlo: https://stackoverflow.com/a/593030

In .NET 4.5 v'è ora built in support for zip files , così per il tuo esempio sarebbe:

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

Se si dispone di un array di byte che contiene un archivio zip con un singolo file, è possibile utilizzare il 01 Classeper ottenere un array di byte non compresso con i dati del file. ZipArchive è contenuto in .NET 4.5, nell'assieme System.IO.Compression.FileSystem (è necessario fare riferimento in modo esplicito).

La seguente funzione, adattato da this answer, funziona per me:

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 
}