ZipOutputStream と ZipInputStream の扱い方サンプル。
CRCと圧縮後サイズを指定しないといけないのだが、CRCはともかく圧縮後サイズは圧縮してみないと分からないので2回同じ処理をしている。
import java.io.File; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.OutputStream; import java.io.IOException; import java.util.zip.CRC32; import java.util.zip.Deflater; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; public class ZipOutputStreamSample { /** * @param 出力先ZIPファイル名 入力ファイル1 入力ファイル2 .. */ public static void main(String[] args) { if(args.length < 2){ System.out.println("args: ZipFileName file1 file2 .."); System.exit(1); } String[] fileList = new String[args.length -1]; System.arraycopy(args, 1, fileList, 0, args.length-1); (new ZipOutputStreamSample()).execute(args[0], fileList); } /** * @param zipName 出力先ZIPファイル名 * @param fileList 入力ファイル名のリスト */ public static void execute(String zipName, String[] fileList){ // 圧縮サイズのリスト。 long[] compSizeList = new long[fileList.length]; // まずは圧縮サイズを求める。 try { // 圧縮先ファイルへのストリームを開く ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipName)); for (int i = 0; i < fileList.length; i++) { File file = new File(fileList[i]); //System.out.println("test: " + getCompressedSize(file)); compSizeList[i] = putFileToZip(out,file,-1); if(compSizeList[i] != -1){ System.out.println(fileList[i] + " size = " + String.valueOf(file.length()) + " compress size = " + compSizeList[i] ); }else{ System.out.println("Failed to open " + fileList[i]); } } // 出力ストリームを閉じる out.flush(); out.close(); } catch (IOException e) { e.printStackTrace(); } // 圧縮サイズを指定して今度こそ正しいZIPファイルを作る。 try { // 圧縮先ファイルへのストリームを開く ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipName)); for (int i = 0; i < fileList.length; i++) { File file = new File(fileList[i]); // 1回目で失敗しなかった分だけ処理。 if(compSizeList[i] != -1){ long ret = putFileToZip(out, file, compSizeList[i]); if(ret == -1){ System.out.println(fileList[i] + " : なぜか2回目の処理で失敗してしまいました。"); } } } // 出力ストリームを閉じる out.flush(); out.close(); } catch (IOException e) { e.printStackTrace(); } } /** * ファイルを1つ ZipOutputStream に書き込む。 * 圧縮後のサイズが分かっているなら compSize を指定する。分からないなら -1 にする。 * 戻り値は圧縮後のサイズ。何かエラーが起きたら -1 。 */ private static long putFileToZip(ZipOutputStream out, File file, long compSize){ BufferedInputStream in; byte[] buf = new byte[256]; CRC32 crc = new CRC32(); long outSize = -1; try { // CRC32を求める。 int size; in = new BufferedInputStream(new FileInputStream(file)); while ((size = in.read(buf, 0, buf.length)) != -1) { crc.update(buf, 0, size); } in.close(); } catch (IOException e) { e.printStackTrace(); return -1; } try { // エントリを作成する。 ZipEntry entry = new ZipEntry(file.getName()); // 圧縮メソッド設定。 entry.setMethod(ZipEntry.DEFLATED); // 圧縮前サイズ設定。 entry.setSize(file.length()); // CRCを設定。書き込み始める前に設定しないとだめらしい。 entry.setCrc(crc.getValue()); // 圧縮後サイズが分かっているなら設定。 if(compSize != -1) entry.setCompressedSize(compSize); //System.out.println("size: " + entry.getSize()); //System.out.println("crc : " + entry.getCrc()); out.putNextEntry(entry); // 圧縮元ファイルの内容を書き込む。 in = new BufferedInputStream(new FileInputStream(file)); int size; while ((size = in.read(buf, 0, buf.length)) != -1) { crc.update(buf, 0, size); out.write(buf, 0, size); } in.close(); // エントリを閉じる。 out.closeEntry(); // ここで初めて圧縮サイズが分かる。 outSize = entry.getCompressedSize(); //System.out.println("cmp : " + outSize); // 一応、ストリームをフラッシュする。 out.flush(); } catch (IOException e) { e.printStackTrace(); return -1; } return outSize; } } |