JavaでZipファイルを処理する

 Javajava.util.zip配下には、圧縮・解凍など、Zipファイルを処理するクラスが定義されている。
 これらを使って、Zipファイルの作成、解凍、圧縮ファイル一覧を取得するクラスを書いてみる。

ソースコード

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.CRC32;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

public class ZipIO {
	private static final int EOF=-1;
	private ZipFile zip;
	private byte[] buf;
	private String path=null;
	
	private ZipIO(){
		buf=new byte[8092];
	}
	
	/**
	 * Zip内のファイル一覧を取得するメソッド
	 * 
	 * @param f zipファイル
	 * @return 圧縮ファイルのリスト
	 */
	public static List<String> getList(File f){
		ZipIO z=new ZipIO();
		return z.listZip(f);
	}
	
	/**
	 * Zipファイルを解凍するメソッド
	 * 
	 * @param dir	解凍先のディレクトリ
	 * @param zip	解凍するZipファイル
	 * @return		解凍の正否
	 */
	public static boolean meltZip(File dir,File zip){
		ZipIO z=new ZipIO();
		z.path=dir.getAbsolutePath();
		return z.meltZip(zip);
	}
	
	/**
	 * Zipファイルを作成するメソッド
	 * 
	 * @param zip		作成するZipファイル名
	 * @param basepath	圧縮ファイルの基準ディレクトリ
	 * @param files		圧縮するファイル・ディレクトリの配列
	 * @return			圧縮の正否
	 */
	public static boolean createZip(File zip,File basepath,File[] files){
		ZipIO z=new ZipIO();
		z.path=basepath.getAbsolutePath()+File.separator;
		return z.freezeeZip(zip,files);
	}
	
	private boolean freezeeZip(File zip,File[] entry){
		try{
			ZipOutputStream zos=
					new ZipOutputStream(new FileOutputStream(zip));
			for(int i=0;i<entry.length;i++){
				freezeFile(zos,entry[i]);
			}
			zos.close();
			return true;
		}catch(IOException e){
			e.printStackTrace();
			return false;
		}
	}
	
	private void freezeFile(ZipOutputStream zos, File file){
		if(file.isDirectory()){
			File[] ff=file.listFiles();
			for(int i=0;i<ff.length;i++){
				freezeFile(zos,ff[i]);
			}
		}else{
			System.out.println("ファイルを圧縮中....");
			long num=addEntryFile(zos, file);
			long v=Math.round((double)num/(double)file.length()*100.0);
			System.out.println(
					"ファイルを圧縮中完了("+Long.toString(v)+"%)");
		}
	}
	
	private long addEntryFile(ZipOutputStream zos, File file) {
		CRC32 crc=new CRC32();
		try{
			BufferedInputStream bis=new BufferedInputStream(
					new FileInputStream(file));
			String tmp=file.getAbsolutePath();
			tmp=tmp.replace(path, "");
			ZipEntry entry=new ZipEntry(tmp);
			int size;
			byte[] bb=getFileBytes(file);
			crc.update(bb,0,(int)file.length());
			entry.setSize(file.length());
			entry.setCrc(crc.getValue());
			zos.putNextEntry(entry);
			while((size=bis.read(buf,0,1024))!=EOF) {
				zos.write(buf,0,size);
			}
			bis.close();
			zos.closeEntry(); 
			return entry.getCompressedSize();
		} catch (Exception e){
			e.printStackTrace();
			return -1;
		}
	}
	
	private static byte[] getFileBytes(File file) {
		 FileInputStream fis = null;
		 BufferedInputStream bis = null;
		 try {
			 int len = (int)file.length();
			 fis = new FileInputStream(file);
			 bis = new BufferedInputStream(fis, len);
			 byte buf[] = new byte[len];
			 bis.read(buf, 0, len);
			 return buf;
		 } catch (IOException e) {
			e.printStackTrace();
		 } finally {
			bis=null;
		 }
		 return null;
	 }
	
	private boolean meltZip(File f){
		try{
			zip=new ZipFile(f.getAbsolutePath());
			Enumeration<? extends ZipEntry> enu=zip.entries();
			while(enu.hasMoreElements()){
				extractFile((ZipEntry)enu.nextElement());
			}
			return true;
		}catch(IOException e){
			e.printStackTrace();
			return false;
		}
	}
	
	private List<String> listZip(File f){
		try{
			zip=new ZipFile(f.getAbsolutePath());
			Enumeration<? extends ZipEntry> enu=zip.entries();
			List<String> ret=new ArrayList<String>();
			while(enu.hasMoreElements()){
				ret.addAll(listFile((ZipEntry)enu.nextElement()));
			}
			return ret;
		}catch(IOException e){
			e.printStackTrace();
			return null;
		}
	}
	
	private void extractFile(ZipEntry entry) throws IOException{
		String name=entry.getName();
		if(name.endsWith("/")){
			name=path+File.separator+name;
			File dir=new File(name);
			if(!dir.exists()){
				dir.mkdirs();
			}
		}else{
			if(name.contains("/")){
				String[] dir=name.split("/");
				String tmp=path+File.separator;
				for(int i=0;i<dir.length-1;i++){
					File d=new File(tmp+dir[i]);
					if(!d.exists())d.mkdir();
					tmp=tmp+dir[i]+File.separator;
				}
				name=path+File.separator+name;
				write(name,entry);
			}else if(name.contains("\\")){
				String[] dir=name.split("\\\\");
				String tmp=path+File.separator;
				for(int i=0;i<dir.length-1;i++){
					File d=new File(tmp+dir[i]);
					if(!d.exists())d.mkdir();
					tmp=tmp+dir[i]+File.separator;
				}
				name=path+File.separator+name;
				write(name,entry);
			}else{
				name=path+File.separator+name;
				write(name,entry);
			}
		}
	}
	
	private void write(String name,ZipEntry entry) throws IOException{
		FileOutputStream fs=new FileOutputStream(name);
		InputStream is=zip.getInputStream(entry);
		File ff=new File(name);
		System.out.println(ff.getAbsolutePath());
		int n;
		while((n=is.read(buf))>0){
			fs.write(buf,0,n);
		}
		is.close();
		fs.close();
	}
	
	private List<String> listFile(ZipEntry entry) throws IOException{
		List<String> ret=new ArrayList<String>();
		String name=entry.getName();
		if(entry.isDirectory()){
			ret.add("Dir :"+name);
		}else{
			ret.add("File:"+name);
		}
		return ret;
	}
}

■結果
 ZipIOは、コンストラクタをprivateにしているので、インスタンスは生成できず、メソッドは、全てstaticメソッドとして提供しています。
 getListがファイル一覧が取得、meltZipが解凍、createZipが圧縮を実行するメソッドです。