2011-11-21 17 views
6

Pracuję w języku C#, a ja pobieram do Internetu plik zip z jednym plikiem XML. i chcę załadować ten plik XML. To, co mam tak daleko:Rozpakowywanie strumienia w języku 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; 
} 

w document.Load Ja zawsze otrzymuję następujący wyjątek:
liczba magiczna w nagłówku GZIP nie jest poprawna. Upewnij się, że przekazujesz strumień GZip.

Co robię źle?

+1

Czy pobierając 'GZip' lub' Zip'? Te dwie nie są takie same. – Oded

+0

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

+0

Myślę, że to mój pierwszy błąd. Jest to plik zip, a nie Gzip. –

Odpowiedz

5

Używam SharpZipLib i działa świetnie!

Poniżej znajduje się funkcja, która hermetyzacji biblioteki

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

Od GZipStream Class opisem:

Compressed GZipStream obiektów zapisywane w pliku z rozszerzeniem .gz mogą być rozpakowane przy użyciu wielu narzędzi wspólny kompresji ; Jednak ta klasa nie natury zapewniają funkcjonalność dodawania plików do lub pobierania plików z archiwum .zip

Więc chyba można kontrolować pliki server-side, bym Proponuję szuka konkretnego zip kierowane biblioteki (np SharpZipLib).

2

Jak wspomnieli inni, GZip i Zip nie są takie same, więc może być konieczne użycie biblioteki zip. Używam biblioteki o nazwie: DotNetZip - dostępne z poniższej strony:

http://dotnetzip.codeplex.com/

4

Widocznie SharpZipLib obecnie unmaintained i prawdopodobnie chcesz, aby tego uniknąć: https://stackoverflow.com/a/593030

W .NET 4.5 jest teraz built in support for zip files , więc dla przykładu byłoby:

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

Jeśli masz tablicę bajtów, który zawiera archiwum zip z jednego pliku, można użyć ZipArchive, aby uzyskać rozpakowaną tablicę bajtów z danymi pliku. ZipArchive jest zawarty w .NET 4.5, w zespole System.IO.Compression.FileSystem (należy odwołać się do niego jawnie).

Poniższa funkcja, zaadaptowany z this answer, działa na mnie:

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 
}