Hacer un archivo ZIP plano

Su archivo zip puede tener otros archivos zip dentro. Es posible que desee extraer el contenido del archivo zip anidado en el archivo principal para obtener una estructura plana.

Estructura de archivo actual
outer.zip
 ├first.txt
 ├inner.zip
 │ ├game.exe
 │ └subitem.bin
 └picture.gif
Estructura de archivo deseada
flatten.zip
 ├first.txt
 ├picture.gif
 ├game.exe
 └subitem.bin

Si no está familiarizado con Aspose.Zip, lea primero cómo extraer archivo zip.

Explicación general

Primero, necesitamos enumerar todas las entradas del archivo. Las entradas regulares deben mantenerse tal como están, ni siquiera debemos descomprimirlas. Las entradas que son archivos en sí mismas deben extraerse a la memoria y eliminarse del archivo externo. Su contenido debe incluirse en el archivo principal.

Detección de entradas que son archivos

Decidamos qué entradas son archivos en sí. Podemos resolver esto por la extensión del nombre de la entrada. Más adelante eliminaremos esas entradas del archivo principal, así que manténgalas en una lista.

1if (entry.Name.EndsWith(".zip", StringComparison.InvariantCultureIgnoreCase)) {
2    entriesToDelete.Add(entry);
3    ...
4}

Extrayendo el contenido de la entrada a la memoria

Aspose.Zip permite extraer el contenido de la entrada zip en cualquier flujo de escritura, no solo en un archivo. Entonces, podemos extraer un archivo anidado a una secuencia de memoria.

Tenga en cuenta: la memoria virtual debe ser lo suficientemente grande para guardar todo el contenido extraído.

1MemoryStream innerCompressed = new MemoryStream();
2entry.Open().CopyTo(innerCompressed); 

Después de eso, la secuencia internalCompressed contiene el archivo interno en sí. El Constructor de archivo permite descomprimir la secuencia proporcionada. Entonces, podemos extraerlo también:

1Archive inner = new Archive(innerCompressed);

Excluyendo entradas

Podemos eliminar una entrada del archivo zip con método particular.

1foreach (ArchiveEntry e in entriesToDelete) { outer.DeleteEntry(e); }

Ponlo todo junto

Aquí está el algoritmo completo.

 1    using (Archive outer = new Archive("outer.zip"))
 2    {
 3        List<ArchiveEntry> entriesToDelete = new List<ArchiveEntry>();
 4        List<string> namesToInsert = new List<string>();
 5        List<MemoryStream> contentToInsert = new List<MemoryStream>();
 6
 7        foreach (ArchiveEntry entry in outer.Entries)
 8        {
 9            if (entry.Name.EndsWith(".zip", StringComparison.InvariantCultureIgnoreCase)) // Find an entry which is an archive itself
10            {
11                entriesToDelete.Add(entry); // Keep reference to the entry in order to remove it from the archive later
12                MemoryStream innerCompressed = new MemoryStream();
13                entry.Open().CopyTo(innerCompressed); //This extracts the entry to a memory stream
14
15                using (Archive inner = new Archive(innerCompressed)) // We know that content of the entry is an zip archive so we may extract
16                {
17                    foreach (ArchiveEntry ie in inner.Entries) // Loop over entries of inner archive
18                    {
19                        namesToInsert.Add(ie.Name); // Keep the name of inner entry.
20                        MemoryStream content = new MemoryStream();
21                        ie.Open().CopyTo(content);
22                        contentToInsert.Add(content); // Keep the content of inner entry.
23                    }
24                }
25            }
26        }
27
28        foreach (ArchiveEntry e in entriesToDelete) 
29            outer.DeleteEntry(e); // Delete all the entries which are archives itself
30
31        for (int i = 0; i < namesToInsert.Count; i++)    
32            outer.CreateEntry(namesToInsert[i], contentToInsert[i]); // Adds entries which were entries of inner archives
33        
34        outer.Save("flatten.zip");
35    }

Subscribe to Aspose Product Updates

Get monthly newsletters & offers directly delivered to your mailbox.