Cómo crear un archivo ZIP plano

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

Estructura actual del archivo
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 listar todas las entradas del archivo. Las entradas normales deben mantenerse tal cual, ni siquiera debemos descomprimirlas. Las entradas que son archivos en sí mismas deben ser extraídas a la memoria y eliminadas del archivo externo. Su contenido debe ser incluido en el archivo principal.

Detección de entradas que son archivos

Decidamos qué entradas son archivos. Podemos averiguarlo por la extensión del nombre de la entrada. Más tarde vamos a eliminar las entradas del archivo principal, por lo que mantener este tipo de entradas en una lista.

1if(entry.getName().toLowerCase(Locale.ROOT).endsWith(".zip")) {
2    entriesToDelete.add(entrada);
3    ...
4}

Extrayendo el contenido de la entrada a la memoria

Aspose.Zip permite extraer el contenido de una entrada zip a cualquier flujo escribible, no sólo a un archivo. Así, podemos extraer un archivo anidado a un flujo de memoria.

Nota: la memoria virtual debe ser lo suficientemente grande como para guardar todo el contenido extraído.

1byte[] b = nuevo byte[8192];
2int bytesRead;
3InputStream entryStream = entry.open();
4ByteArrayOutputStream innerCompressed = new ByteArrayOutputStream();
5while (0 < (bytesRead = entryStream.read(b, 0, b.length)) {
6    innerCompressed.write(b, 0, bytesRead);
7}

Después de eso innerCompressed stream contiene el propio archivo interno. El Constructor de archivo permite descomprimir el flujo proporcionado. Por lo tanto, también podemos extraerlo:

1Archive inner = new Archive(new ByteArrayInputStream(innerCompressed.toByteArray()));

Excluyendo entradas

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

1for(ArchiveEntry e : entriesToDelete) {
2    outer.deleteEntry(e);
3}

Ponerlo todo junto

Aquí está el algoritmo completo.

 1try(Archivo externo = nuevo Archivo("externo.zip")) {
 2    ArrayList<ArchiveEntry> entriesToDelete = new ArrayList<ArchiveEntry>();
 3    ArrayList<String> namesToInsert = new ArrayList<String>();
 4    ArrayList<InputStream> contentToInsert = new ArrayList<InputStream>();
 5    for(ArchiveEntry entry : outer.getEntries()) {
 6        // Buscar una entrada que sea un archivo propiamente dicho
 7        if(entry.getName().toLowerCase(Locale.ROOT).endsWith(".zip")) {
 8            // Guarda la referencia a la entrada para poder eliminarla del archivo más adelante
 9            entriesToDelete.add(entrada);
10
11            //This extracts the entry to a memory stream
12            byte[] b = new byte[8192];
13            int bytesRead;
14            InputStream entryStream = entry.open();
15            ByteArrayOutputStream innerCompressed = new ByteArrayOutputStream();
16            while (0 < (bytesRead = entryStream.read(b, 0, b.length))) {
17                innerCompressed.write(b, 0, bytesRead);
18            }
19
20            // We know that content of the entry is a zip archive, so we may extract
21            try(Archive inner = new Archive(new ByteArrayInputStream(innerCompressed.toByteArray()))) {
22
23                // Loop over entries of inner archive
24                for(ArchiveEntry ie : inner.getEntries()) {
25
26                    // Keep the name of inner entry.
27                    namesToInsert.add(ie.getName());
28
29                    InputStream ieStream = ie.open();
30                    ByteArrayOutputStream content = new ByteArrayOutputStream();
31                    while (0 < (bytesRead = ieStream.read(b, 0, b.length))) {
32                        content.write(b, 0, bytesRead);
33                    }
34
35                    // Keep the content of inner entry.
36                    contentToInsert.add(new ByteArrayInputStream(content.toByteArray()));
37                }
38            }
39        }
40    }
41
42    for(ArchiveEntry e : entriesToDelete) {
43        // Delete all the entries which are archives itself
44        outer.deleteEntry(e);
45    }
46
47    for(int i = 0; i < namesToInsert.size(); i++) {
48        // Adds entries which were entries of inner archives
49        outer.createEntry(namesToInsert.get(i), contentToInsert.get(i));
50    }
51
52    outer.save("flatten.zip");
53} catch (Exception ex) {
54    System.out.println(ex);
55}
Subscribe to Aspose Product Updates

Get monthly newsletters & offers directly delivered to your mailbox.