使用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);
}
}
}
參考資料:
http://www.cnblogs.com/CUCmehp/archive/2008/10/28/1320872.html
http://hi.baidu.com/yezongbo/blog/item/1b7960fd6aae661308244d14.html
除了Java平臺本身提供的API之外,我還發現一個開源的項目,Truezip (http://truezip.java.net/)有機會再研究吧。
附件是兩個助手類文件,可下載使用(將.png後綴刪除即可):