2012-07-19 13 views
14

Buduję aplikację w stylu metra dla Windows 8 i mam plik zip, który pobieram z serwisu WWW i chcę go rozpakować.rozpakuj plik ZIP na Windows 8 C#

Widziałem próbki do kompresji i dekompresji, ale to zajmuje jeden plik, kompresuje/dekompresuje go. Mam całą strukturę katalogów, którą muszę wyodrębnić.

Oto co mam do tej pory:

var appData = ApplicationData.Current; 
var file = await appData.LocalFolder.GetItemAsync("thezip.zip") as StorageFile; 
var decompressedFile = await ApplicationData.Current.LocalFolder.CreateFileAsync("tempFileName", CreationCollisionOption.GenerateUniqueName); 
using (var decompressor = new Decompressor(await file.OpenSequentialReadAsync())) 
using (var decompressedOutput = await decompressedFile.OpenAsync(FileAccessMode.ReadWrite)) 
{ 
    var bytesDecompressed = await RandomAccessStream.CopyAsync(decompressor, decompressedOutput); 
} 

Ale to nie jest dobre, zmienna bytesDecompressed jest zawsze zerowej wielkości, ale jest plik ZIP 1.2MB

Any help tutaj byłby znacznie docenione.

EDIT: Odpowiedź dzięki Mahantesh

Oto kod do rozpakowania pliku:

private async void UnZipFile() 
{ 
    var folder = ApplicationData.Current.LocalFolder; 

    using (var zipStream = await folder.OpenStreamForReadAsync("thezip.zip")) 
    { 
     using (MemoryStream zipMemoryStream = new MemoryStream((int)zipStream.Length)) 
     { 
      await zipStream.CopyToAsync(zipMemoryStream); 

      using (var archive = new ZipArchive(zipMemoryStream, ZipArchiveMode.Read)) 
      { 
       foreach (ZipArchiveEntry entry in archive.Entries) 
       { 
        if (entry.Name != "") 
        { 
         using (Stream fileData = entry.Open()) 
         { 
          StorageFile outputFile = await folder.CreateFileAsync(entry.Name, CreationCollisionOption.ReplaceExisting); 
          using (Stream outputFileStream = await outputFile.OpenStreamForWriteAsync()) 
          { 
           await fileData.CopyToAsync(outputFileStream); 
           await outputFileStream.FlushAsync(); 
          } 
         } 
        } 
       } 
      } 
     } 
    } 
} 
+0

I ve zaimplementował ten kod, aby rozpakować plik zip obecny w folderze ApplicationData.Current.LocalFolder. Ale zip zawiera foldery i podfoldery. Tak więc kod po uruchomieniu daje komunikat "Błąd odmowy dostępu" podczas oczekiwania na działanie outputFile.OpenStreamForWriteAsync() w tych podfolderach. Jednak błąd był widoczny w każdym losowym podfolderze, gdy kod był uruchamiany wiele razy. Masz pomysł? –

+0

Ok .. Błąd polegał na tym, że utworzyłem metodę UnZipFile jako metodę statyczną, której nie powinienem był zrobić ... –

Odpowiedz

4

podstawie kodu i sugestie, wpadłem na taki, który wspiera ekstrakcji foldery, który był jednym z moich potrzeb:

private async void UnZipFile(string file) 
{ 
    var folder = ApplicationData.Current.LocalFolder; 

    using (var zipStream = await folder.OpenStreamForReadAsync(file)) 
    { 
     using (MemoryStream zipMemoryStream = new MemoryStream((int)zipStream.Length)) 
     { 
      await zipStream.CopyToAsync(zipMemoryStream); 

      using (var archive = new ZipArchive(zipMemoryStream, ZipArchiveMode.Read)) 
      { 
       foreach (ZipArchiveEntry entry in archive.Entries) 
       { 

        if (entry.Name == "") 
        { 
         // Folder 
         await CreateRecursiveFolder(folder, entry); 
        } 
        else 
        { 
         // File 
         await ExtractFile(folder, entry); 
        } 
       } 
      } 
     } 
    } 
} 

private async Task CreateRecursiveFolder(StorageFolder folder, ZipArchiveEntry entry) 
{ 
    var steps = entry.FullName.Split('/').ToList(); 

    steps.RemoveAt(steps.Count() - 1); 

    foreach (var i in steps) 
    { 
     await folder.CreateFolderAsync(i, CreationCollisionOption.OpenIfExists); 

     folder = await folder.GetFolderAsync(i); 
    } 
} 

private async Task ExtractFile(StorageFolder folder, ZipArchiveEntry entry) 
{ 
    var steps = entry.FullName.Split('/').ToList(); 

    steps.RemoveAt(steps.Count() - 1); 

    foreach (var i in steps) 
    { 
     folder = await folder.GetFolderAsync(i); 
    } 

    using (Stream fileData = entry.Open()) 
    { 
     StorageFile outputFile = await folder.CreateFileAsync(entry.Name, CreationCollisionOption.ReplaceExisting); 

     using (Stream outputFileStream = await outputFile.OpenStreamForWriteAsync()) 
     { 
      await fileData.CopyToAsync(outputFileStream); 
      await outputFileStream.FlushAsync(); 
     } 
    } 
} 
+0

, to dobrze, ale w jaki sposób otrzymasz powiadomienie, gdy cały proces zakończony? – balint

+1

Zdaj sobie sprawę, że używam ** oczekuj ** dla metod 'CreateRecursiveFolder' i' ExtractFile', więc nie będzie to prawdziwie asynchroniczne, a metoda 'UnZipFile' zwróci tylko wtedy, gdy wszystko będzie gotowe. Musisz użyć klauzula 'await' podczas wywoływania' UnZipFile'. – Tuco

+0

@Tuco Zaimplementowałem ten kod, aby rozpakować plik zip obecny w moim folderze ApplicationData.Current.LocalFolder. Ale zip zawiera foldery i podfoldery. Tak więc kod daje "błąd odmowy dostępu" podczas rozpakowywania danych w tych podfolderach. Jednak błąd był widoczny w każdym losowym podfolderze, gdy kod był uruchamiany wiele razy. Masz pomysł? –