Java IO操作--壓縮包zip實現工具類
壓縮檔案大致可以分為三種:ZIP、JAR、GZ。
壓縮流
在日常的使用中經常會使用到像WinRAR或WinZIP這樣的壓縮檔案,通過這些軟體可以把一個很大的檔案進行壓縮以方便傳輸。
在JAVA中 為了減少傳輸時的資料量也提供了專門的壓縮流,可以將檔案或資料夾壓縮成ZIP、JAR、GZIP等檔案的格式。
壓縮流的實現:正常情況下在IO操作中,所有的類庫都是在io包中。
在JAVA IO中,不僅可以實現ZIP壓縮格式的輸入、輸出,也可以實現JAR及GZIP檔案格式的壓縮:
JAR壓縮的支援類儲存在java.util.jar包中,常用的類有如下幾個: JAR壓縮輸出流:JarOutputStream JAR壓縮輸入流:JarInputStream JAR檔案:JARFile JAR實體:JAREntry
GZIP是用於UNIX系統的檔案壓縮,在Linux中經常會使用到*.gz的檔案,就是GZIP格式,GZIP壓縮的支援類儲存在java.util.zip包中,常用的類有如下幾個: GZIP壓縮輸出流:GZIPOutputStream GZIP壓縮輸入流:GZIPInputStream
ZIP是一種較為常見的壓縮形式,在Java中要想實現ZIP的壓縮需要匯入java.util.zip包,可以使用此包中的ZipFile、ZipOutputStream、ZipInputStream、ZipEntry幾個類完成。
1)ZipEntry:API文件 在每一個壓縮檔案中都會存在多個子檔案,那麼這每一個的子檔案在JAVA中就使用ZipEntry表示。 在例項化ZipEntry的時候,要設定名稱,此名稱實際上就是壓縮檔案中的每一個元素中的名稱
建立具有指定名稱的新zip條目。 |
建立一個新的zip條目,其中包含從指定的zip條目中獲取的欄位。 |
boolean |
如果這是目錄條目,則返回true。 |
2)ZipFile:API文件
是一個專門表示壓縮檔案的類,在JAVA中,每一個壓縮檔案都可以使用ZipFile表示,還可以使用ZipFile根據壓縮後的檔名稱找到每一個壓縮檔案中的ZipEntry並將其進行解壓縮操作。ZipFile在例項化的時候必須接收File類的例項,此File類的例項是指向一個壓縮的*.zip檔案。
3)ZipInputStream:
可以不用輸入實體名稱,就可以得到每一個ZipEntry物件
void |
關閉當前ZIP條目並定位流以讀取下一個條目。 |
4)ZipOutputStream:API文件 如果要想完成一個檔案或資料夾的壓縮,要使用ZipOutputStream類完成,ZipOutputStream是OutputStream的子類。
此類的功能就是完成ZIP格式輸出的
void |
close()
關閉ZIP輸出流以及要過濾的流。 |
void |
關閉當前ZIP條目並定位流以寫入下一個條目。 |
void |
開始編寫新的ZIP檔案條目並將流定位到條目資料的開頭。 |
總結: 1、壓縮檔案中的每一個壓縮實體都使用ZipEntry儲存,一個壓縮檔案中可能包含一個或多個ZipEntry物件。 2、在JAVA中可以進行zip、jar、gz三種格式的壓縮支援,操作流程基本上是一致的。 3、ZipOutputStream可以進行壓縮的輸出,但是輸出的位置不一定是檔案。 4、ZipFile表示每一個壓縮檔案,可以得到每一個壓縮實體的輸入流。
1、單檔案壓縮:
public static void main(String[] args) throws Exception {
File file = new File("E:\\java\\file01\\使用者Table基本資訊.xlsx");
String zipFilePath = "E:\\java\\file04";
ZipFileUtil.zipOneFile(zipFilePath, file);
}
2、 遞迴實現巢狀檔案或不巢狀資料夾的壓縮
對一個資料夾進行壓縮,例如,現在在某盤存在一個liuxun的資料夾。從使用各種壓縮軟體的經驗來看,如果現在要進行壓縮的話,則在壓縮之後的檔案中應該存在一個liuxun的資料夾。在資料夾中應該存放著各個壓縮檔案。所以在實現的時候就應該列出資料夾中的全部內容,並把每一個內容設定成ZipEntry的物件,儲存到壓縮檔案之中。
public static void main(String[] args) throws Exception {
File fileDir = new File("E:\\java\\file01");
String zipFilePath = "E:\\java\\file04";
ZipFileUtil.zipFileDir(zipFilePath, fileDir, true);
}
3、解壓縮檔案到指定目錄下
如果指定目錄或檔案不存在,則應該進行建立操作。
public static void main(String[] args) throws Exception {
File zipfile = new File("E:\\java\\file04\\file01.zip"); // 定義壓縮檔名稱
String descDir = "E:\\java\\file04";
ZipFileUtil.unZipFile(zipfile, descDir);
}
4、自定義工具類:FileToZipUtil
public class ZipFileUtil {
/**
* 壓縮一個檔案
*
* @param zipFilePath 宣告壓縮檔案路徑
* @param file 要壓縮的檔案
* @throws Exception
*/
public static void zipOneFile(String zipFilePath, File file) throws Exception {
// 檢查目錄是否存在,不存在時建立
File dir = new File(zipFilePath);
if (!dir.isDirectory()) {
dir.mkdirs();
}
File zipFile = new File(dir, file.getName().substring(0, file.getName().indexOf(".")) + ".zip"); // 定義壓縮檔名稱
ZipOutputStream zipOut = null; // 宣告壓縮流物件
try {
InputStream input = new FileInputStream(file);
zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
zipOut.putNextEntry(new ZipEntry(file.getName())); // 設定ZipEntry物件
zipOut.setComment("UTF-8"); // 設定註釋
byte[] buffer = new byte[1024];
int len = -1;
while ((len = input.read(buffer)) != -1) {
zipOut.write(buffer, 0, len);
}
input.close();
} finally {
if (zipOut != null) {
zipOut.flush();
zipOut.closeEntry();
zipOut.close();
}
}
}
/**
* 壓縮一個檔案返回輸出流
*
* @param zipFilePath
* @param file
* @return OutputStream
* @throws Exception
*/
public static OutputStream zipOneFileToOut(String zipFilePath, File file) throws Exception {
// 檢查目錄是否存在,不存在時建立
File dir = new File(zipFilePath);
if (!dir.isDirectory()) {
dir.mkdirs();
}
File zipFile = new File(dir, file.getName().substring(0, file.getName().indexOf(".")) + ".zip"); // 定義壓縮檔名稱
ZipOutputStream zipOut = null; // 宣告壓縮流物件
try {
InputStream input = new FileInputStream(file);
zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
zipOut.putNextEntry(new ZipEntry(file.getName())); // 設定ZipEntry物件
zipOut.setComment("UTF-8"); // 設定註釋
byte[] buffer = new byte[10240];
int len = -1;
while ((len = input.read(buffer)) != -1) {
zipOut.write(buffer, 0, len);
}
input.close();
} finally {
if (zipOut != null) {
zipOut.flush();
zipOut.closeEntry();
zipOut.close();
}
}
return zipOut;
}
/**
* 壓縮一個巢狀檔案或不巢狀資料夾
*
* @param zipFilePath 宣告壓縮檔案路徑
* @param fileDir 要壓縮的資料夾
* @param dirFlag 要壓縮的資料夾是否巢狀資料夾,true巢狀;false沒有
* @throws Exception
*/
public static void zipFileDir(String zipFilePath, File fileDir, boolean dirFlag) throws Exception {
// 檢查目錄是否存在,不存在時建立
File dir = new File(zipFilePath);
if (!dir.isDirectory()) {
dir.mkdirs();
}
ZipOutputStream zipOut = null; // 宣告壓縮流物件
InputStream input = null;
try {
File zipFile = new File(dir, fileDir.getName() + ".zip"); // 定義壓縮檔名稱
zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
zipOut.setComment("UTF-8"); // 設定註釋
if (fileDir.isDirectory()) { // 判斷是否是資料夾
File[] files = fileDir.listFiles();
for (File fileSec : files) {
if (dirFlag) {
recursionZip(zipOut, fileSec, fileDir.getName() + File.separator);
} else {
recursionZip(zipOut, fileSec, fileDir.getName() + File.separator);
}
}
}
} finally {
if (zipOut != null) {
zipOut.flush();
zipOut.closeEntry();
zipOut.close();
}
}
}
/**
* 遞迴實現巢狀檔案或不巢狀資料夾的壓縮 void
*
* @param zipOut
* @param file
* @param baseDir
* @throws Exception
*/
private static void recursionZip(ZipOutputStream zipOut, File file, String baseDir) throws Exception {
if (file.isDirectory()) {
File[] files = file.listFiles();
for (File fileSec : files) {
recursionZip(zipOut, fileSec, baseDir + file.getName() + File.separator); // 遞迴
}
} else {
InputStream input = new FileInputStream(file);
zipOut.putNextEntry(new ZipEntry(baseDir + file.getName())); // 設定ZipEntry物件: 解壓檔案會在原檔案目錄下
zipOut.setComment("UTF-8"); // 設定註釋
byte[] buffer = new byte[1024];
int len = -1;
while ((len = input.read(buffer)) != -1) {
zipOut.write(buffer, 0, len);
}
input.close();
}
}
/**
* 功能:解壓縮
*
* @param file:需要解壓縮的檔案
* @param descDir:解壓後的目標目錄
* @throws IOException
* @throws ZipException
*/
public static void unZipFile(File file, String descDir) throws Exception {
ZipFile zipFile = new ZipFile(file); // 例項化ZipFile物件
ZipInputStream zipInput = new ZipInputStream(new FileInputStream(file)); // 例項化壓縮輸入流
ZipEntry entry = null;
OutputStream out = null; // 定義輸出流,用於輸出每一個實體內容
InputStream input = null; // 定義輸入流,讀取每一個ZipEntry
while((entry = zipInput.getNextEntry()) != null){ // 得到每一個壓縮實體物件
//System.out.println("解壓縮 " + entry.getName() + "檔案。");
File outFile = new File(descDir + File.separator + entry.getName()); // 定義要輸出的路徑檔案
if(!outFile.getParentFile().exists()){ // 如果輸出資料夾不存在
outFile.getParentFile().mkdir() ; // 建立資料夾
}
if(!outFile.exists()){ // 判斷輸出檔案是否存在
outFile.createNewFile() ; // 建立檔案
}
try {
input = zipFile.getInputStream(entry); // 得到每一個壓縮實體物件的輸入流
out = new FileOutputStream(outFile); // 例項化檔案輸出流
byte[] buffer = new byte[1024];
int len = -1;
while ((len = input.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
} finally {
input.close() ;
out.close() ;
}
}
}
}
參考文章:
中文亂碼的問題都是基於JDK6,但是在JDK7中已經解決了,只要把JDK版本升到7就可以。