Erstellen Sie ein flaches ZIP-Archiv
Ihr Zip-Archiv enthält möglicherweise andere Zip-Archive. Möglicherweise 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 das ZIP-Archiv entpackt.
Allgemeine Erklärung
Zuerst müssen wir alle Einträge des Archivs auflisten. Reguläre Einträge sollten so bleiben, 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.
Einträge erkennen, bei denen es sich um Archive handelt
Lassen Sie uns entscheiden, welche Einträge selbst Archive sind. Wir können dies durch die Erweiterung des Eintragsnamens herausfinden. Später werden wir diese Einträge aus dem Hauptarchiv entfernen. Behalten Sie diese Einträge daher in einer Liste.
1if (entry.Name.EndsWith(".zip", StringComparison.InvariantCultureIgnoreCase)) {
2 entriesToDelete.Add(entry);
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 Speicherstream extrahieren.
Bitte beachten Sie: Der virtuelle Speicher muss groß genug sein, um alle extrahierten Inhalte zu behalten.
1MemoryStream innerCompressed = new MemoryStream();
2entry.Open().CopyTo(innerCompressed);
Danach enthält der innerCompressed-Stream das innere Archiv selbst. Der Archivkonstruktor ermöglicht die Dekomprimierung des bereitgestellten Streams. Also können wir es auch extrahieren:
1Archive inner = new Archive(innerCompressed);
Einträge ausgenommen
Mit bestimmter Methode können wir einen Eintrag aus dem Zip-Archiv entfernen.
1foreach (ArchiveEntry e in entriesToDelete) { outer.DeleteEntry(e); }
Füge alles zusammen
Hier ist der vollständige Algorithmus.
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 }