package util;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
/**
* Zip壓縮/解壓縮工具類
* 實現對目標路徑及其子路徑下的全部文件及空目錄的壓縮
* 參考網上若干種實現,並修改其bug
*/
public class ZipUtil {
/** 緩衝器大小 */
private static final int BUFFER = 512;
/**
* 取的給定源目錄下的全部文件及空的子目錄
* 遞歸實現
*
* @param srcFile
*
* @return
*/
private static List<File> getAllFiles(File srcFile) {
List<File> fileList = new ArrayList<File>();
File[] tmp = srcFile.listFiles();
for (int i = 0; i < tmp.length; i++) {
if (tmp[i].isFile()) {
fileList.add(tmp[i]);
System.out.println("add file: "+tmp[i].getName());
}
if (tmp[i].isDirectory()) {
if (tmp[i].listFiles().length!=0){//若不是空目錄,則遞歸添加其下的目錄和文件
fileList.addAll(getAllFiles(tmp[i]));
}
else{//如果空目錄,則添加這個目錄到fileList
fileList.add(tmp[i]);
System.out.println("add empty dir: "+tmp[i].getName());
}
}
} // end for
return fileList;
}
/**
* 取相對路徑
* 依據文件名和壓縮源路徑獲得文件在壓縮源路徑下的相對路徑
*
* @param dirPath 壓縮源路徑
* @param file
*
* @return 相對路徑
*/
private static String getRelativePath(String dirPath, File file) {
File dir = new File(dirPath);
String relativePath = file.getName();
while (true) {
file = file.getParentFile();
if (file == null) {
break;
}
if (file.equals(dir)) {
break;
} else {
relativePath = file.getName() + "/" + relativePath;
}
} // end while
return relativePath;
}
/**
* 建立文件
* 根據壓縮包內文件名和解壓縮目的路徑,建立解壓縮目標文件,
* 生成中間目錄
* @param dstPath 解壓縮目的路徑
* @param fileName 壓縮包內文件名
*
* @return 解壓縮目標文件
*
* @throws IOException
*/
private static File createFile(String dstPath, String fileName) throws IOException {
String[] dirs = fileName.split("/");//將文件名的各級目錄分解
File file = new File(dstPath);
if (dirs.length > 1) {//文件有上級目錄
for (int i = 0; i < dirs.length - 1; i++) {
file = new File(file, dirs[i]);//依次建立文件對象知道文件的上一級目錄
}
if (!file.exists()) {
file.mkdirs();//文件對應目錄若不存在,則建立
System.out.println("mkdirs: " + file.getCanonicalPath());
}
file = new File(file, dirs[dirs.length - 1]);//建立文件
return file;
} else {
if (!file.exists()) {
file.mkdirs();//若目標路徑的目錄不存在,則建立
System.out.println("mkdirs: " + file.getCanonicalPath());
}
file = new File(file, dirs[0]);//建立文件
return file;
}
}
/**
* 解壓縮方法
*
*
* @param zipFileName 壓縮文件名
* @param dstPath 解壓目標路徑
*
* @return
*/
public static boolean unzip(String zipFileName, String dstPath) {
System.out.println("zip uncompressing...");
try {
ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(zipFileName));
ZipEntry zipEntry = null;
byte[] buffer = new byte[BUFFER];//緩衝器
int readLength = 0;//每次讀出來的長度
while ((zipEntry = zipInputStream.getNextEntry()) != null) {
if (zipEntry.isDirectory()) {//如果zip條目目錄,則需建立這個目錄
File dir = new File(dstPath + "/" + zipEntry.getName());
if (!dir.exists()) {
dir.mkdirs();
System.out.println("mkdirs: " + dir.getCanonicalPath());
continue;//跳出
}
}
File file = createFile(dstPath, zipEntry.getName());//如果文件,則需建立該文件
System.out.println("file created: " + file.getCanonicalPath());
OutputStream outputStream = new FileOutputStream(file);
while ((readLength = zipInputStream.read(buffer, 0, BUFFER)) != -1) {
outputStream.write(buffer, 0, readLength);
}
outputStream.close();
System.out.println("file uncompressed: " + file.getCanonicalPath());
} // end while
} catch (FileNotFoundException e) {
System.out.println(e.getMessage());
e.printStackTrace();
System.out.println("unzip fail!");
return false;
} catch (IOException e) {
System.out.println(e.getMessage());
e.printStackTrace();
System.out.println("unzip fail!");
return false;
}
System.out.println("unzip success!");
return true;
}
/**
* 壓縮方法
* (能夠壓縮空的子目錄)
* @param srcPath 壓縮源路徑
* @param zipFileName 目標壓縮文件
*
* @return
*/
public static boolean zip(String srcPath, String zipFileName) {
System.out.println("zip compressing...");
File srcFile = new File(srcPath);
List<File> fileList = getAllFiles(srcFile);//全部要壓縮的文件
byte[] buffer = new byte[BUFFER];//緩衝器
ZipEntry zipEntry = null;
int readLength = 0;//每次讀出來的長度
try {
ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(zipFileName));
for (File file : fileList) {
if (file.isFile()){//如果文件,則壓縮這個文件
zipEntry = new ZipEntry(getRelativePath(srcPath, file));
zipEntry.setSize(file.length());
zipEntry.setTime(file.lastModified());
zipOutputStream.putNextEntry(zipEntry);
InputStream inputStream = new BufferedInputStream(new FileInputStream(file));
while ((readLength = inputStream.read(buffer, 0, BUFFER)) != -1) {
zipOutputStream.write(buffer, 0, readLength);
}
inputStream.close();
System.out.println("file compressed: " + file.getCanonicalPath());
}else {//如果目錄(即空目錄)則將這個目錄寫入zip條目
zipEntry = new ZipEntry(getRelativePath(srcPath, file)+"/");
zipOutputStream.putNextEntry(zipEntry);
System.out.println("dir compressed: " + file.getCanonicalPath()+"/");
}
} // end for
zipOutputStream.close();
} catch (FileNotFoundException e) {
System.out.println(e.getMessage());
e.printStackTrace();
System.out.println("zip fail!");
return false;
} catch (IOException e) {
System.out.println(e.getMessage());
e.printStackTrace();
System.out.println("zip fail!");
return false;
}
System.out.println("zip success!");
return true;
}
}
java