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