フラット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
Asopsion.Zipに慣れていない場合は、 Zip Archiveを抽出最初に[抽出]方法を読んでください。
過剰説明
まず、アーカイブのすべてのエントリをリストする必要があります。通常のエントリはそのまま保持する必要があります。それらを減圧することさえしてはいけません。アーカイブ自体であるエントリは、メモリに抽出し、外側のアーカイブから削除する必要があります。彼らのコンテンツはメインアーカイブに含める必要があります。
アーカイブであるエントリの検出
どのエントリがアーカイブ自体であるかを決定しましょう。エントリ名の延長によってこれを把握できます。 後でこれらのエントリをメインアーカイブから削除しますので、そのようなエントリをリストに保管してください。
1if(entry.getname()。tolowercase(locale.root).endswith( "。zip")){
2 entriestodelete.add(entry);
3 ...
4}
エントリのコンテンツをメモリに抽出します
Aspose.zipを使用すると、ファイルだけでなく、writableストリームへのzipエントリのコンテンツを抽出できます。そのため、ネストされたアーカイブをメモリストリームに抽出できます。
注意:仮想メモリは、抽出されたすべてのコンテンツを保持するのに十分な大きさでなければなりません。
1byte [] b = new 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}
その後、内部で複雑なストリームには、内側のアーカイブ自体が含まれています。 アーカイブコンストラクターにより、提供されるストリームを減圧できます。 だから、私たちもそれを抽出することができます:
1Archive Inner = new Archive(new bytearrayinputStream(innerCompressed.tobytearray()));
エントリを除く
特定の方法を使用して、zipアーカイブからエントリを削除できます。
1for(archiveentry e:entriestodelete){
2 outer.deleteentry(e);
3}
すべてをまとめる
これが完全なアルゴリズムです。
1try(アーカイブouter = new Archive( "outer.zip")){
2 arrayList <ArchiveEntry> entriestodelete = new ArrayList <ArchiveEntry>();
3 arrayList <string> namestoinsert = new ArrayList <String>();
4 arrayList <inuptStream> contentToInsert = new ArrayList <inputStream>();
5 for(archiveentry entry:outer.getentries()){
6 //アーカイブ自体であるエントリを見つけます
7 if(entry.getname()。tolowercase(locale.root).endswith( "。zip")){
8 //後でアーカイブから削除するために、エントリを参照してください
9 entriestodelete.add(entry);
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(例外Ex){
54 System.out.println(ex);
55}