Créer une archive ZIP à plat

Votre archive zip peut contenir d’autres archives zip. On souhaitera peut-être extraire le contenu de l’archive zip imbriquée dans l’archive parent pour obtenir une structure plate.

Structure actuelle des archives
outer.zip
 ├first.txt
 ├inner.zip
 │ ├game.exe
 │ └subitem.bin
 └picture.gif
Structure d'archive souhaitée
flatten.zip
 ├first.txt
 ├picture.gif
 ├game.exe
 └subitem.bin

Si vous n’êtes pas familier avec Aspose.Zip, lisez d’abord comment extraire l’archive zip.

Explication générale

Tout d’abord, nous devons lister toutes les entrées de l’archive. Les entrées régulières doivent être conservées telles quelles, il ne faut même pas les décompresser. Les entrées qui sont elles-mêmes des archives doivent être extraites de la mémoire et supprimées de l’archive externe. Leur contenu doit être inclus dans l’archive principale.

Détection des entrées qui sont des archives

Décidons quelles entrées sont elles-mêmes des archives. Nous pouvons comprendre cela par extension du nom de l’entrée. Plus tard, nous supprimerons ces entrées de l’archive principale, conservez donc ces entrées dans une liste.

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

Extraction du contenu de l’entrée en mémoire

Aspose.Zip permet d’extraire le contenu d’une entrée zip dans n’importe quel flux inscriptible, pas seulement dans un fichier. Ainsi, nous pouvons extraire une archive imbriquée dans un flux mémoire.

Attention : la mémoire virtuelle doit être suffisamment grande pour conserver tout le contenu extrait.

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

Après ce flux innerCompressed contient l’archive interne elle-même. Le Constructeur d’archive permet de décompresser le flux fourni. Nous pouvons donc l’extraire également :

1Archive inner = new Archive(innerCompressed);

Hors entrées

Nous pouvons supprimer une entrée de l’archive zip avec méthode particulière.

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

Mettez tout cela ensemble

Voici l’algorithme complet.

 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.