2012-07-19 31 views
14

Estoy construyendo una aplicación de estilo metro para Windows 8 y tengo un archivo zip que estoy descargando desde un servicio web, y quiero extraerlo.descomprimir un archivo ZIP en Windows 8 C#

He visto la muestra para compresión y descompresión, pero eso toma un solo archivo y lo comprime/descomprime. Tengo toda una estructura de directorios que necesito extraer.

Esto es lo que tengo hasta ahora:

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); 
} 

Pero esto no es bueno, la variable es siempre bytesDecompressed tamaño cero, pero el archivo zip es 1,2 MB

Cualquier ayuda aquí sería enormemente apreciado.

EDIT: respuesta, gracias a Mahantesh

Aquí está el código para descomprimir un archivo:

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' he implementado este código para descomprimir un archivo zip presente en mi carpeta ApplicationData.Current.LocalFolder. Pero el archivo zip contiene carpetas y subcarpetas. Entonces, el código, cuando se ejecuta, da "Error de acceso denegado" mientras se realiza la operación aguardar outputFile.OpenStreamForWriteAsync() en estas subcarpetas. Sin embargo, el error se vio en cualquier subcarpeta aleatoria cuando el código se ejecutó varias veces. ¿Alguna idea sobre esto? –

+0

Ok ... el error fue que había hecho el método UnZipFile como un método estático que no debería haber hecho ... –

Respuesta

13

En las aplicaciones estilo Metro, se trabaja con archivos comprimidos mediante el uso de los métodos en la ZipArchive, ZipArchiveEntry , DeflateStream y clases de GZipStream.

Consulte: UnZip File in Metro

Consulte: Folder zip/unzip in metro c#

+0

gracias, actualicé mi pregunta para mostrar la respuesta – Mark

4

Sobre la base de su código y sugerencias, se me ocurrió una que admite la extracción de carpetas, que era una de mis necesidades:

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

eso está bien, pero cómo se notifica cuando todo proceso terminado? – balint

+1

Date cuenta de que estoy usando ** await ** para los métodos 'CreateRecursiveFolder' y' ExtractFile', por lo que no será realmente asíncrono, y el método 'UnZipFile' solo volverá cuando todo esté listo. Tienes que usar el 'cláusula await' cuando se llama al' UnZipFile'. – Tuco

+0

@Tuco He implementado este código para descomprimir un archivo comprimido presente en mi carpeta ApplicationData.Current.LocalFolder. Pero el archivo zip contiene carpetas y subcarpetas. Entonces, el código da "Error de acceso denegado" al descomprimir datos en estas subcarpetas. Sin embargo, el error se vio en cualquier subcarpeta aleatoria cuando el código se ejecutó varias veces. ¿Alguna idea sobre esto? –

Cuestiones relacionadas