So erstellen Sie ein flaches ZIP-Archiv
Ihr Zip-Archiv kann andere Zip-Archive enthalten. Vielleicht möchten Sie den Inhalt des verschachtelten Zip-Archivs in das übergeordnete Archiv extrahieren, um eine flache Struktur zu erhalten.
Aktuelle Archivstruktur
outer.zip ├first.txt ├inner.zip │ ├game.exe │ └subitem.bin └picture.gif
Gewünschte Archivstruktur
flatten.zip ├first.txt ├picture.gif ├game.exe └subitem.bin
Wenn Sie mit Aspose.Zip nicht vertraut sind, lesen Sie zuerst, wie man Zip-Archiv extrahiert.
Einfache Erklärung
Zuerst müssen wir alle Einträge des Archivs auflisten. Reguläre Einträge sollten so belassen werden, wie sie sind, wir sollten sie nicht einmal dekomprimieren. Einträge, die selbst Archive sind, müssen in den Speicher extrahiert und aus dem äußeren Archiv entfernt werden. Ihr Inhalt muss in das Hauptarchiv aufgenommen werden.
Erkennen von Einträgen, die Archive sind
Lassen Sie uns entscheiden, welche Einträge selbst Archive sind. Wir können dies anhand der Erweiterung des Eintragsnamens herausfinden. Später werden wir diese Einträge aus dem Hauptarchiv entfernen, also behalten wir solche Einträge in einer Liste.
1if(eintrag.getName().toLowerCase(Locale.ROOT).endsWith(".zip")) {
2 entriesToDelete.add(Eintrag);
3 ...
4}
Inhalt des Eintrags in den Speicher extrahieren
Aspose.Zip ermöglicht das Extrahieren des Inhalts eines Zip-Eintrags in einen beliebigen beschreibbaren Stream, nicht nur in eine Datei. Wir können also ein verschachteltes Archiv in einen Speicherstrom extrahieren.
Bitte beachten Sie: Der virtuelle Speicher muss groß genug sein, um alle extrahierten Inhalte zu speichern.
1byte[] b = new byte[8192];
2int bytesLesen;
3InputStream entryStream = entry.open();
4ByteArrayOutputStream innerCompressed = new ByteArrayOutputStream();
5while (0 < (bytesRead = entryStream.read(b, 0, b.length))) {
6 innerCompressed.write(b, 0, bytesRead);
7}
Danach enthält innerCompressed stream das innere Archiv selbst. Der Archive constructor ermöglicht die Dekomprimierung des bereitgestellten Streams. Wir können ihn also auch extrahieren:
1Archive inner = new Archive(new ByteArrayInputStream(innerCompressed.toByteArray()));
Einträge ausschließen
Mit bestimmte Methode können wir einen Eintrag aus dem Zip-Archiv entfernen.
1for(ArchiveEntry e : entriesToDelete) {
2 outer.deleteEntry(e);
3}
Alles zusammenfügen
Hier ist der vollständige Algorithmus.
1try(Archiv outer = new Archiv("outer.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 // Einen Eintrag finden, der selbst ein Archiv ist
7 if(entry.getName().toLowerCase(Locale.ROOT).endsWith(".zip")) {
8 // Behalte den Verweis auf den Eintrag, um ihn später aus dem Archiv entfernen zu können
9 entriesToDelete.add(Eintrag);
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}