ZipOutputStream と ZipInputStream の扱い方サンプル。
CRCと圧縮後サイズを指定しないといけないのだが、CRCはともかく圧縮後サイズは圧縮してみないと分からないので2回同じ処理をしている。

ZipOutputStreamSample.java

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;
    }
}
戻る