使用Java操作zip文件

使用Java操作zip文件

 

 

Java提供了操作zip文件的API,具體來說,它們位於:java.util.zip 包中,以下的兩個工具類分別用於創建zip文件、展開(解壓縮)zip文件。

 

創建zip文件的助手類:

/**
 * @author INC062805
 * 
 */
public class ZipHelper {
	// 靜態創建起
	public static ZipHelper create(File input, File output) {
		// 檢查參數
		if (input == null || !input.exists()) {
			throw new IllegalArgumentException("input is NULL or not exist!");
		}
		if (output == null) {
			throw new IllegalArgumentException("output can not be NULL!");
		}

		return new ZipHelper(input, output);
	}

	// 隱藏構建器
	ZipHelper(File input, File output) {
		this.input = input;
		this.output = output;
	}

	// 開始執行壓縮
	public boolean start() {
		OutputStream out = null;
		try {
			out = new BufferedOutputStream(new FileOutputStream(output));
			ZipOutputStream zipOut = new ZipOutputStream(out);

			zipOut.setLevel(ZipEntry.STORED);
			zip(zipOut, input, input);

			zipOut.flush();
			zipOut.finish();
			zipOut.close();

			return true;
		} catch (Exception e) {
			// e.printStackTrace();
			return false;
		} finally {
			IOUtils.quietCloseOutputStream(out);
		}
	}

	// 執行壓縮,input:輸入文件(可以是目錄),rootDir:起始目錄
	private void zip(ZipOutputStream out, File input, File rootDir)
			throws IOException {
		if (input == null || !input.exists()) {
			return;
		}
		if (input.isDirectory()) {
			zipDirectory(out, input, rootDir);
		} else {
			zipFile(out, input, rootDir);
		}

	}

	// 向ZipOutputStream中添加目錄,dir:輸入目錄,rootDir:起始目錄
	private void zipDirectory(ZipOutputStream out, File dir, File rootDir)
			throws IOException {
		// 檢查input目錄,是否是系統頂級目標,例如:c:\ or /
		if (rootDir.getParentFile() == null) {
			// SKIP ROOT DIR
		}

		if (!onlyFile) {
			String name = getEntryNameString(dir, rootDir) + '/';
			out.putNextEntry(new ZipEntry(name));
			// System.out.println("zip.dir:" + entry.getName());
		}

		File[] files = dir.listFiles();
		for (File f : files) {
			zip(out, f, rootDir);
		}
	}

	// 向ZipOutputStream中 添加文件
	private void zipFile(ZipOutputStream out, File file, File rootDir)
			throws IOException {
		//
		ZipEntry entry = new ZipEntry(getEntryNameString(file, rootDir));
		out.putNextEntry(entry);

		InputStream in = null;
		try {
			in = new FileInputStream(file);
			IOUtils.copy(in, out);
			out.closeEntry();
			// System.out.println("zip.file:" + entry.getName());
		} finally {
			IOUtils.quietCloseInputStream(in);
		}
	}

	// 通過輸入文件(名稱),取得在Zip Entry中應該有的名稱
	private String getEntryNameString(final File input, final File rootDir) {
		if (onlyFile) {
			return input.getName();
		}

		// 檢查是否是root
		if (input.equals(rootDir)) {
			return input.getName();
		}

		// 確認回溯前的起始位置
		final File parent = rootDir.getParentFile();
		File file = input;

		// 回溯 直到找到 root
		StringBuilder ret = new StringBuilder();
		do {
			if (ret.length() > 0) {
				ret.insert(0, '/');
			}
			ret.insert(0, file.getName());
			file = file.getParentFile();

		} while (file != null && !file.equals(parent));

		return ret.toString();
	}

	// 是否更新已存在的輸出文件
	// private boolean update = false;
	// 是否僅僅打包文件,忽略目錄結構
	private boolean onlyFile = false;
	// 輸入輸出
	private final File input;
	private final File output;

	public boolean isOnlyFile() {
		return onlyFile;
	}

	public void setOnlyFile(boolean onlyFile) {
		this.onlyFile = onlyFile;
	}
}
 

展開zip文件的助手類:

/**
 * @author INC062805
 * 
 *         展開zip文件的助手類
 */
public class UnZipHelper {
	//
	public static UnZipHelper create(File srcZipFile, File destDir) {
		return new UnZipHelper(srcZipFile, destDir);
	}

	//
	private File srcZipFile, destDir;
	private CharSequence error = null;

	// 隱藏構建器
	private UnZipHelper(File srcZipFile, File destDir) {
		this.srcZipFile = srcZipFile;
		this.destDir = destDir;
	}

	// 取得錯誤信息
	public CharSequence getErrorInfo() {
		return error;
	}

	// 展開src 指定的zip文件到 目標位置dest
	public boolean start() {
		return start(true);
	}

	// 展開src 指定的zip文件到 目標位置dest,並自動創建頂級目錄
	public boolean start(boolean autoCreateTopDir) {
		// 自動創建頂級目錄 --- 與zip文件同名
		if (autoCreateTopDir) {
			String name = srcZipFile.getName();

			// 析除擴展名
			int pos = name.lastIndexOf('.');
			if (pos > 0) {
				name = name.substring(0, pos);
			}

			destDir = new File(destDir, name);
			destDir.mkdirs();
		}

		try {
			ZipFile zf = new ZipFile(srcZipFile);
			Enumeration<? extends ZipEntry> e = zf.entries();
			boolean bool = false;
			while (e.hasMoreElements()) {
				ZipEntry ze = e.nextElement();
				// 處理目錄
				if (ze.isDirectory()) {
					bool = expandDirectory(ze, destDir);
					continue;
				}
				// 處理文件
				bool = expandFile(zf, ze, destDir);
			}
			return bool;
		} catch (Exception e) {
			error = "open zipfile Error:(" + e.getLocalizedMessage() + ")";
			return false;
		}
	}

	// 解壓縮目錄元素 到目標位置
	private boolean expandDirectory(ZipEntry ze, File destDir) {
		File dir = new File(destDir, ze.getName());
		boolean bool = dir.exists() ? true : dir.mkdirs();
		// System.out.println("Expand.Dir:" + dir.getAbsolutePath());
		if (!bool) {
			error = "create Dest Directory Error,:-(";
		}
		return bool;
	}

	// 解壓縮文件元素到目標目錄下
	private boolean expandFile(ZipFile zf, ZipEntry ze, File destDir) {
		// 定位到目標目錄
		String name = ze.getName();
		File dir = locateDestDirectory(name, destDir);

		// 確認目標文件位置
		int pos = name.lastIndexOf('/');
		if (pos > 0) {
			name = name.substring(pos + 1);
		}

		// 從zip 輸入流中創建 目標文件
		return makeFile(new File(dir, name), zf, ze);
	}

	// 定位目標實體的所在目錄
	private File locateDestDirectory(String path, File destDir) {
		File dir = destDir;
		int pos = path.indexOf('/');
		while (pos > 0) {
			dir = new File(dir, path.substring(0, pos));
			path = path.substring(pos + 1);
			pos = path.indexOf('/');
		}
		return dir;
	}

	//
	private boolean makeFile(File file, ZipFile zf, ZipEntry ze) {
		OutputStream out = null;
		InputStream in = null;
		try {
			//
			boolean bool = file.exists() ? true : file.createNewFile();
			// System.out.println("create New File:" + bool);
			if (!bool) {
				error = "createNewFile.Error,:-(";
				return false;
			}

			//
			out = new BufferedOutputStream(new FileOutputStream(file));
			in = zf.getInputStream(ze);

			// long len =
			IOUtils.copy(in, out);
			// System.out.println("make New File length:" + len);
			return true;
		} catch (Exception e) {
			error = "makeFile.Error:(" + e.getLocalizedMessage() + ")";
			return false;
		} finally {
			IOUtils.quietCloseOutputStream(out);
			IOUtils.quietCloseInputStream(in);
		}
	}
}
 

參考資料:

解決Zip文件中文名問題

http://www.cnblogs.com/CUCmehp/archive/2008/10/28/1320872.html


加密,解密zip文件、對稱加密,RSA,AES算法

http://hi.baidu.com/yezongbo/blog/item/1b7960fd6aae661308244d14.html


除了Java平臺本身提供的API之外,我還發現一個開源的項目,Truezip (http://truezip.java.net/)有機會再研究吧。

 

附件是兩個助手類文件,可下載使用(將.png後綴刪除即可):

ZipHelper.javaUnZipHelper.java

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章