ZIP アーカイブをフラットにする
zip アーカイブ内に他の zip アーカイブが含まれている可能性があります。ネストされた zip アーカイブの内容を親アーカイブに抽出して、フラットな構造を取得したい場合があります。
現在のアーカイブ構造
outer.zip ├first.txt ├inner.zip │ ├game.exe │ └subitem.bin └picture.gif
必要なアーカイブ構造
flatten.zip ├first.txt ├picture.gif ├game.exe └subitem.bin
Aspose.Zip に慣れていない場合は、最初に zip アーカイブを解凍する 方法をお読みください。
全体的な説明
まず、アーカイブのすべてのエントリをリストする必要があります。通常のエントリはそのまま保持する必要があり、解凍する必要もありません。エントリ自体がアーカイブである場合は、メモリに抽出し、外部アーカイブから削除する必要があります。それらのコンテンツはメイン アーカイブに含める必要があります。
アーカイブであるエントリの検出
どのエントリがアーカイブ自体であるかを決定しましょう。これは、エントリ名の拡張によってわかります。 後でこれらのエントリをメイン アーカイブから削除するので、そのようなエントリはリストに保存しておいてください。
1if (entry.Name.EndsWith(".zip", StringComparison.InvariantCultureIgnoreCase)) {
2 entriesToDelete.Add(entry);
3 ...
4}
エントリのコンテンツをメモリに抽出しています
Aspose.Zip を使用すると、zip エントリのコンテンツをファイルだけでなく、書き込み可能なストリームに抽出できます。したがって、ネストされたアーカイブをメモリ ストリームに抽出できます。
注意: 仮想メモリは、抽出されたすべてのコンテンツを保持するのに十分な大きさである必要があります。
1MemoryStream innerCompressed = new MemoryStream();
2entry.Open().CopyTo(innerCompressed);
その後、 innerCompressed ストリームには内部アーカイブ自体が含まれます。 Archive コンストラクター を使用すると、提供されたストリームを解凍できます。 したがって、次のように抽出することもできます。
1Archive inner = new Archive(innerCompressed);
エントリーを除く
特定の方法 を使用して、zip アーカイブからエントリを削除できます。
1foreach (ArchiveEntry e in entriesToDelete) { outer.DeleteEntry(e); }
すべてをまとめてください
完全なアルゴリズムは次のとおりです。
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 }