使用ant-1.8.4.jar中的org.apache.tools.zip包進行文件的文件壓縮和解壓,主要使用該jar包中的以下類:
org.apache.tools.zip.ZipEntry;
org.apache.tools.zip.ZipFile;
org.apache.tools.zip.ZipOutputStream;
下面是我寫的壓縮和解壓文件的工具類,並附測試,請大傢為我debug:
[java]
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.CRC32;
import java.util.zip.CheckedOutputStream;
import java.util.zip.Deflater;
import java.util.zip.ZipException;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipFile;
import org.apache.tools.zip.ZipOutputStream;
/**
* @Description:
* 壓縮和解壓工具
*/
public class ZipUtil {
/**
* @Description:
* 壓縮文件
* @param sourcePath 將要壓縮的文件或目錄的路徑,請使用絕對路徑
* @param zipPath 生成壓縮文件的路徑,請使用絕對路徑。如果該路徑以“.zip”為結尾,
* 則壓縮文件的名稱為此路徑;如果該路徑不以“.zip”為結尾,則壓縮文件的名稱
* 為該路徑加上將要壓縮的文件或目錄的名稱,再加上以“.zip”結尾
* @param encoding 壓縮編碼
* @param comment 壓縮註釋
*/
public static void compress(String sourcePath, String zipPath, String encoding, String comment)
throws FileNotFoundException, IOException {
// 判斷要壓縮的文件是否存在
File sourceFile = new File(sourcePath);
if (!sourceFile.exists() || (sourceFile.isDirectory() && sourceFile.list().length == 0)) {
throw new FileNotFoundException("要壓縮的文件或目錄不存在,或者要壓縮的目錄為空");
}
// 設置壓縮文件路徑,默認為將要壓縮的路徑的父目錄為壓縮文件的父目錄
if (zipPath == null || "".equals(zipPath)) {
String sourcePathName = sourceFile.getAbsolutePath();
int index = sourcePathName.lastIndexOf(".");
zipPath = (index > -1 ? sourcePathName.substring(0, index) : sourcePathName) + ".zip";
} else {
// 如果壓縮路徑為目錄,則將要壓縮的文件或目錄名做為壓縮文件的名字,這裡壓縮路徑不以“.zip”為結尾則認為壓縮路徑為目錄
if(!zipPath.endsWith(".zip")){
// 如果將要壓縮的路徑為目錄,則以此目錄名為壓縮文件名;如果將要壓縮的路徑為文件,則以此文件名(去除擴展名)為壓縮文件名
String fileName = sourceFile.getName();
int index = fileName.lastIndexOf(".");
zipPath = zipPath + File.separator + (index > -1 ? fileName.substring(0, index) : fileName) + ".zip";
}
}
// 設置解壓編碼
if (encoding == null || "".equals(encoding)) {
encoding = "GBK";
}
// 要創建的壓縮文件的父目錄不存在,則創建
File zipFile = new File(zipPath);
if (!zipFile.getParentFile().exists()) {
zipFile.getParentFile().mkdirs();
}
// 創建壓縮文件輸出流
FileOutputStream fos = null;
try {
fos = new FileOutputStream(zipPath);
} catch (FileNotFoundException e) {
if (fos != null) {
try{ fos.close(); } catch (Exception e1) {}
}
}
// 使用指定校驗和創建輸出流
CheckedOutputStream csum = new CheckedOutputStream(fos, new CRC32());
// 創建壓縮流
ZipOutputStream zos = new ZipOutputStream(csum);
// 設置編碼,支持中文
zos.setEncoding(encoding);
// 設置壓縮包註釋
zos.setComment(comment);
// 啟用壓縮
zos.setMethod(ZipOutputStream.DEFLATED);
// 設置壓縮級別為最強壓縮
zos.setLevel(Deflater.BEST_COMPRESSION);
// 壓縮文件緩沖流
BufferedOutputStream bout = null;
try {
// 封裝壓縮流為緩沖流
bout = new BufferedOutputStream(zos);
// 對數據源進行壓縮
compressRecursive(zos, bout, sourceFile, sourceFile.getParent());
} finally {
if (bout != null) {
try{ bout.close(); } catch (Exception e) {}
}
}
}
/**
* @Description:
* 壓縮文件,支持將多個文件或目錄壓縮到同一個壓縮文件中
* @param sourcePath 將要壓縮的文件或目錄的路徑的集合,請使用絕對路徑
* @param zipPath 生成壓縮文件的路徑,請使用絕對路徑。該路不能為空,並且必須以“.zip”為結尾
* @param encoding 壓縮編碼
* @param comment 壓縮註釋
*/
public static void compress(List<String> sourcePaths, String zipPath, String encoding, String comment)
throws FileNotFoundException, IOException {
// 設置壓縮文件路徑,默認為將要壓縮的路徑的父目錄為壓縮文件的父目錄
if (zipPath == null || "".equals(zipPath) || !zipPath.endsWith(".zip")) {
throw new FileNotFoundException("必須指定一個壓縮路徑,而且該路徑必須以'.zip'為結尾");
}
// 設置解壓編碼
if (encoding == null || "".equals(encoding)) {
encoding = "GBK";
}
// 要創建的壓縮文件的父目錄不存在,則創建
File zipFile = new File(zipPath);
if (!zipFile.getParentFile().exists()) {
zipFile.getParentFile().mkdirs();
}
// 創建壓縮文件輸出流
FileOutputStream fos = null;
try {
fos = new FileOutputStream(zipPath);
} catch (FileNotFoundException e) {
if (fos != null) {
try{ fos.close(); } catch (Exception e1) {}
}
}
// 使用指定校驗和創建輸出流
CheckedOutputStream csum = new CheckedOutputStream(fos, new CRC32());
// 創建壓縮流
ZipOutputStream zos = new ZipOutputStream(csum);
// 設置編碼,支持中文
zos.setEncoding(encoding);
// 設置壓縮包註釋
zos.setComment(comment);
// 啟用壓縮
zos.setMethod(ZipOutputStream.DEFLATED);
// 設置壓縮級別為最強壓縮
zos.setLevel(Deflater.BEST_COMPRESSION);
// 壓縮文件緩沖流
BufferedOutputStream bout = null;
try {
// 封裝壓縮流為緩沖流
bout = new BufferedOutputStream(zos);
// 迭代壓縮每一個路徑
for (int i=0,len=sourcePaths.size(); i<len; i++) {
// 獲取每一個壓縮路徑
File sourceFile = new File(sourcePaths.get(i));
// 對數據源進行壓縮
compressRecursive(zos, bout, sourceFile, sourceFile.getParent());
}
} finally {
if (bout != null) {
try{ bout.close(); } catch (Exception e) {}
}
}
}
/**
* @Description:
* 壓縮文件時,所使用的迭代方法
* @param zos 壓縮輸出流
* @param bout 封裝壓縮輸出流的緩沖流
* @param sourceFile 將要壓縮的文件或目錄的路徑
* @param prefixDir 整個將要壓縮的文件或目錄的父目錄,傳入此值為瞭獲取壓縮條目的名稱
*/
private static void compressRecursive(ZipOutputStream zos, BufferedOutputStream bout,
File sourceFile, String prefixDir) throws IOException, FileNotFoundException {
// 獲取壓縮條目名,初始時將要壓縮的文件或目錄的相對路徑
String entryName = sourceFile.getAbsolutePath().substring(prefixDir.length() + File.separator.length());
// 判斷是文件還是目錄,如果是目錄,則繼續迭代壓縮
if (sourceFile.isDirectory()) {
// 如果是目錄,則需要在目錄後面加上分隔符('/')
//ZipEntry zipEntry = new ZipEntry(entryName + File.separator);
//zos.putNextEntry(zipEntry);
// 獲取目錄中的文件,然後迭代壓縮
File[] srcFiles = sourceFile.listFiles();
for (int i = 0; i < srcFiles.length; i++) {
// 壓縮
compressRecursive(zos, bout, srcFiles[i], prefixDir);
}
} else {
// 開始寫入新的ZIP文件條目並將流定位到條目數據的開始處
ZipEntry zipEntry = new ZipEntry(entryName);
// 向壓縮流中寫入一個新的條目
zos.putNextEntry(zipEntry);
// 讀取將要壓縮的文件的輸入流
BufferedInputStream bin = null;
try{
// 獲取輸入流讀取文件
bin = new BufferedInputStream(new FileInputStream(sourceFile));
// 讀取文件,並寫入壓縮流
byte[] buffer = new byte[1024];
int readCount = -1;
while ((readCount = bin.read(buffer)) != -1) {
bout.write(buffer, 0, readCount);
}
// 註,在使用緩沖流寫壓縮文件時,一個條件完後一定要刷新,不然可能有的內容就會存入到後面條目中去瞭
bout.flush();
// 關閉當前ZIP條目並定位流以寫入下一個條目
zos.closeEntry();
} finally {
if (bin != null) {
try { bin.close(); } catch (IOException e) {}
}
}
}
}
/**
* @Description:
* 解壓文件
* @param zipPath 被壓縮文件,請使用絕對路徑
* @param targetPath 解壓路徑,解壓後的文件將會放入此目錄中,請使用絕對路徑
* 默認為壓縮文件的路徑的父目錄為解壓路徑
* @param encoding 解壓編碼
*/
public static void decompress(String zipPath, String targetPath, String encoding)
throws FileNotFoundException, ZipException, IOException {
// 獲取解縮文件
File file = new File(zipPath);
if (!file.isFile()) {
throw new FileNotFoundException("要解壓的文件不存在");
}
// 設置解壓路徑
if (targetPath == null || "".equals(targetPath)) {
targetPath = file.getParent();
}
// 設置解壓編碼
if (encoding == null || "".equals(encoding)) {
encoding = "GBK";
}
// 實例化ZipFile對象
ZipFile zipFile = new ZipFile(file, encoding);
// 獲取ZipFile中的條目
Enumeration<ZipEntry> files = zipFile.getEntries();
// 迭代中的每一個條目
ZipEntry entry = null;
// 解壓後的文件
File outFile = null;
// 讀取壓縮文件的輸入流
BufferedInputStream bin = null;
// 寫入解壓後文件的輸出流
BufferedOutputStream bout = null;
while (files.hasMoreElements()) {
// 獲取解壓條目
entry = files.nextElement();
// 實例化解壓後文件對象
outFile = new File(targetPath + File.separator + entry.getName());
// 如果條目為目錄,則跳向下一個
if (entry.getName().endsWith(File.separator)) {
outFile.mkdirs();
continue;
}
// 創建目錄
if (!outFile.getParentFile().exists()) {
outFile.getParentFile().mkdirs();
}
// 創建新文件
outFile.createNewFile();
// 如果不可寫,則跳向下一個條目
if (!outFile.canWrite()) {
continue;
}
try {
// 獲取讀取條目的輸入流
bin = new BufferedInputStream(zipFile.getInputStream(entry));
// 獲取解壓後文件的輸出流
bout = new BufferedOutputStream(new FileOutputStream(outFile));
// 讀取條目,並寫入解壓後文件
byte[] buffer = new byte[1024];
int readCount = -1;
while ((readCount = bin.read(buffer)) != -1) {
bout.write(buffer, 0, readCount);
}
} finally {
try {
bin.close();
bout.flush();
bout.close();
} catch (Exception e) {}
}
}
}
public static void main(String[] args) throws Exception{
//compressTest();
//compressTest2();
//decompressTest();
}
public static void compressTest() throws Exception {
String sourcePath = "E:" + File.separator + "文檔" + File.separator + "音樂";
String zipPath = "E:" + File.separator + "我的音樂.zip";
String comment = "音樂壓縮文件";
compress(sourcePath, zipPath, "GBK", comment);
}
public static void decompressTest() throws Exception {
String zipPath = "E:" + File.separator + "我的音樂.zip";
String targetPath = "E:" + File.separator + "temp";
decompress(zipPath, targetPath, "GBK");
}
public static void compressTest2() throws Exception {
List<String> list = new ArrayList<String>();
list.add("E:" + File.separator + "文檔" + File.separator + "音樂");
list.add("E:" + File.separator + "文檔" + File.separator + "視頻");
list.add("E:" + File.separator + "文檔" + File.separator + "資料");
list.add("E:" + File.separator + "文檔" + File.separator + "書籍");
String zipPath = "E:" + File.separator + "我的文檔壓縮文件.zip";
String comment = "我的文檔壓縮文件";
compress(list, zipPath, "GBK", comment);
}
}