ZIP圧縮をしてみる - part1 zip書き込み -
JavaでZIPファイルを扱うには java.util.zip パッケージを使う。このパッケージはJDK1.1からあるにもかかわらず、ZIP圧縮を説明しているサイトは非常に少ないと思う。まぁ、javadoc読めば分かる、ということなのか。とにかく今回はzipの書き込みをやってみたいと思う。プログラムは下記の通りで、結果は画像*1のようになる。
import java.util.zip.*; import java.io.*; public class Main { public static void main(String[] args) throws Exception { String str = init(); // ZIP保存したい文字列 ZipOutputStream zip = new ZipOutputStream(new FileOutputStream("hoge.zip")); // (1) zip.setLevel(9); // 最高の圧縮レベル zip.putNextEntry(new ZipEntry("piyo1.txt")); // (2) zip.write(str.getBytes(), 0, str.length()*2); // (3) zip.closeEntry(); // (3) zip.putNextEntry(new ZipEntry("piyo2.txt")); zip.write(str.getBytes(), 0, str.length()*2); zip.closeEntry(); zip.putNextEntry(new ZipEntry("hoge/piyo3.txt")); zip.write(str.getBytes(), 0, str.length()*2); zip.closeEntry(); zip.close(); // (5) } static String init() { StringBuilder buf = new StringBuilder(2048); for(int i=1; i<=1024; ++i) buf.append("ほげ"); return buf.toString(); } }
ZIP圧縮ファイルを作るのに必要なクラスは、ZipOutputStreamとZipEntryの2つだけだ。ZipOutputStreamクラスが、ZIPアーカイブを全体を出力するクラスで、これが任意のOutputStreamに結び付けられる。ファイルとして出力するときはFileOutputStreamに結びつければ良い (1)。
ZipEntryが、ZIPアーカイブに入れる「ファイル」や「ディレクトリ」を表す。ZipEntryをnewして、このインスタンスをZipOutputStream#putNextEntry()すれば加えられる (2)。実際にデータを書きこむのは、ZipEntryにではなくZipOutputStrea.write(byte[], int, int)である (3)。このメソッドで現在のZipEntryに書き込む。基本的にZipEntryは読み込みに使うようなので、いくらこのクラスのメソッドを調べてもデータは書き込めない(エントリー情報を設定するsetterメソッドはいくつかある)。書き込むメソッドは、先のwriteしかないから、byte配列しか書き込めない。
ZipEntryに必要なデータをすべて書き込んだら、ZipOutputStream#closeEntry()でZipEntryを閉じる (3)。続けて別のエントリーを書き込みたいときは、(1)〜(3)を繰り返せばよい。
また、ディレクトリを書き込みたいときは、(4)にある通り hoge/piyo.txt のように、エントリー名を /(スラッシュ)で区切って行けばよい。
最後にZipOutputStream#close()で、Zipストリーム自体を閉じる (5)。
やっぱり、あまり難しくなかった。これとjava.io系のディレクトリ捜査やファイル属性取得を組み合わせれば、ディレクトリを丸ごとZIP圧縮ができるだろう。
*1:画像がぼやけて見にくいので撤去しました