生活随笔
收集整理的這篇文章主要介紹了
zip4j -- Java处理zip压缩文件
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
?ZIP4J,作為解決了我的問題的終極解決方案,本來一開始在搜索引擎上就看到了它的蹤跡,但因天朝的網(wǎng)絡(luò)環(huán)境問題,zip4j的官網(wǎng)一直無法訪問,最終使我多走了好多冤枉路,期間試過JDK的zip包,試過Apache的zip解決方案,也試過如winzipaes等其它的開源框架,最終沒有滿足自己的需求,最后,我不得已掛了一下代理將zip4j下載了下來,試用了一下,果然威力無比,所到之處所向披靡...
閑話少說,如果需要可以到zip4j的官網(wǎng)下載該開源項目:
http://www.lingala.net/zip4j/
不過需要提醒的是可能無法直接訪問,如果無法正常訪問,請自行準備代理訪問,如果各位嫌麻煩,可以到這里下載:
http://download.csdn.net/detail/number_chc/7751199
ZIP4J的官方說明
(自己翻譯了一下,英文不好,呵呵...)
Key features(主要特性):
- Create, Add, Extract, Update, Remove files from a Zip file
針對ZIP壓縮文件創(chuàng)建、添加、抽出、更新和移除文件 - Read/Write password protected Zip files
(讀寫有密碼保護的Zip文件) - Supports AES 128/256 Encryption
(支持AES 128/256算法加密) - Supports Standard Zip Encryption
(支持標準Zip算法加密) - Supports Zip64 format
(支持zip64格式) - Supports Store (No Compression) and Deflate compression method
(支持Store(非壓縮)和Deflate壓縮方法---不太明白) - Create or extract files from Split Zip files (Ex: z01, z02,...zip)
(針對分塊zip文件創(chuàng)建和抽出文件) - Supports Unicode file names
(支持Unicode編碼文件名) - Progress Monitor
(進度監(jiān)控)
從上面的主要特性可以看出,zip4j的功能是非常強大的,完全可以利用其寫個類似于好壓的zip文件管理軟件,但我們用地最多的可能還是利用其作一些簡單的解壓和壓縮操作,其它的功能極少觸碰,我也一樣,呵呵...
使用注意點
zip4j默認采用UTF-8編碼,所以它支持中文,同時也支持密碼,而且支持多種壓縮算法,可以說功能強大,但使用起來卻非常簡單,當然,如果需求比較復(fù)雜,那就得好好去研究了。如果你僅僅是簡單地解壓一個zip壓縮文件,那么只需要簡單地幾步即可:
[java] view plaincopy
public?static?void?unzip(File?zipFile,?String?dest,?String?passwd)?throws?ZipException?{????????????ZipFile?zFile?=?new?ZipFile(zipFile);????????????zFile.setFileNameCharset("GBK");?????????????????if?(!zFile.isValidZipFile())?{?????????????????throw?new?ZipException("壓縮文件不合法,可能被損壞.");????????????}????????????File?destDir?=?new?File(dest);???????????????if?(destDir.isDirectory()?&&?!destDir.exists())?{????????????????destDir.mkdir();????????????}????????????if?(zFile.isEncrypted())?{????????????????zFile.setPassword(passwd.toCharArray());????????????}????????????zFile.extractAll(dest);????????????}????
?當然將指定文件壓縮成zip文件也是非常簡單的事,此處不再貼代碼,如有需要請參看下面的完整示例。
?提示:如果將要解壓的壓縮文件中的文件名含有中文,解壓時需要注意一點,就是設(shè)置文件名字符集方法
[java] view plaincopy
zFile.setFileNameCharset("GBK");???
這個方法的調(diào)用一定要靠前,要靠多前呢?其實最好在創(chuàng)建ZipFile之后就設(shè)置上,至少要在
[java] view plaincopy
zFile.isValidZipFile()????
這個方法調(diào)用之前調(diào)用,我在應(yīng)用時因為這個問題耽誤好久,最后查看源碼才弄明白,好像是ZipFile在驗證方法中就將編碼設(shè)置好,以后就不再對文件名編碼作改變了。
完整示例
下面提供一個自己寫的例子,鄙人才疏學淺,天分也差,寫的代碼質(zhì)量很差,斗膽貼上,希望能起到拋磚引玉的作用。
[java] view plaincopy
package?com.ninemax.cul.util;????import?java.io.File;??import?java.util.ArrayList;??import?java.util.Collections;??import?java.util.List;????import?org.apache.commons.lang3.StringUtils;????import?net.lingala.zip4j.core.ZipFile;??import?net.lingala.zip4j.exception.ZipException;??import?net.lingala.zip4j.model.FileHeader;??import?net.lingala.zip4j.model.ZipParameters;??import?net.lingala.zip4j.util.Zip4jConstants;????????????public?class?CompressUtil?{???????????????????????????public?static?File?[]?unzip(String?zip,?String?dest,?String?passwd)?throws?ZipException?{??????????File?zipFile?=?new?File(zip);??????????return?unzip(zipFile,?dest,?passwd);??????}????????????????????????public?static?File?[]?unzip(String?zip,?String?passwd)?throws?ZipException?{??????????File?zipFile?=?new?File(zip);??????????File?parentDir?=?zipFile.getParentFile();??????????return?unzip(zipFile,?parentDir.getAbsolutePath(),?passwd);??????}???????????????????????????public?static?File?[]?unzip(File?zipFile,?String?dest,?String?passwd)?throws?ZipException?{??????????ZipFile?zFile?=?new?ZipFile(zipFile);??????????zFile.setFileNameCharset("GBK");??????????if?(!zFile.isValidZipFile())?{??????????????throw?new?ZipException("壓縮文件不合法,可能被損壞.");??????????}??????????File?destDir?=?new?File(dest);??????????if?(destDir.isDirectory()?&&?!destDir.exists())?{??????????????destDir.mkdir();??????????}??????????if?(zFile.isEncrypted())?{??????????????zFile.setPassword(passwd.toCharArray());??????????}??????????zFile.extractAll(dest);????????????????????List<FileHeader>?headerList?=?zFile.getFileHeaders();??????????List<File>?extractedFileList?=?new?ArrayList<File>();??????????for(FileHeader?fileHeader?:?headerList)?{??????????????if?(!fileHeader.isDirectory())?{??????????????????extractedFileList.add(new?File(destDir,fileHeader.getFileName()));??????????????}??????????}??????????File?[]?extractedFiles?=?new?File[extractedFileList.size()];??????????extractedFileList.toArray(extractedFiles);??????????return?extractedFiles;??????}??????????????????????public?static?String?zip(String?src)?{??????????return?zip(src,null);??????}???????????????????????public?static?String?zip(String?src,?String?passwd)?{??????????return?zip(src,?null,?passwd);??????}????????????????????????public?static?String?zip(String?src,?String?dest,?String?passwd)?{??????????return?zip(src,?dest,?true,?passwd);??????}??????????????????????????????public?static?String?zip(String?src,?String?dest,?boolean?isCreateDir,?String?passwd)?{??????????File?srcFile?=?new?File(src);??????????dest?=?buildDestinationZipFilePath(srcFile,?dest);??????????ZipParameters?parameters?=?new?ZipParameters();??????????parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);?????????????????????parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);??????????????if?(!StringUtils.isEmpty(passwd))?{??????????????parameters.setEncryptFiles(true);??????????????parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_STANDARD);???????????????parameters.setPassword(passwd.toCharArray());??????????}??????????try?{??????????????ZipFile?zipFile?=?new?ZipFile(dest);??????????????if?(srcFile.isDirectory())?{????????????????????????????????????if?(!isCreateDir)?{??????????????????????File?[]?subFiles?=?srcFile.listFiles();??????????????????????ArrayList<File>?temp?=?new?ArrayList<File>();??????????????????????Collections.addAll(temp,?subFiles);??????????????????????zipFile.addFiles(temp,?parameters);??????????????????????return?dest;??????????????????}??????????????????zipFile.addFolder(srcFile,?parameters);??????????????}?else?{??????????????????zipFile.addFile(srcFile,?parameters);??????????????}??????????????return?dest;??????????}?catch?(ZipException?e)?{??????????????e.printStackTrace();??????????}??????????return?null;??????}????????????????????????private?static?String?buildDestinationZipFilePath(File?srcFile,String?destParam)?{??????????if?(StringUtils.isEmpty(destParam))?{??????????????if?(srcFile.isDirectory())?{??????????????????destParam?=?srcFile.getParent()?+?File.separator?+?srcFile.getName()?+?".zip";??????????????}?else?{??????????????????String?fileName?=?srcFile.getName().substring(0,?srcFile.getName().lastIndexOf("."));??????????????????destParam?=?srcFile.getParent()?+?File.separator?+?fileName?+?".zip";??????????????}??????????}?else?{??????????????createDestDirectoryIfNecessary(destParam);????????????????if?(destParam.endsWith(File.separator))?{??????????????????String?fileName?=?"";??????????????????if?(srcFile.isDirectory())?{??????????????????????fileName?=?srcFile.getName();??????????????????}?else?{??????????????????????fileName?=?srcFile.getName().substring(0,?srcFile.getName().lastIndexOf("."));??????????????????}??????????????????destParam?+=?fileName?+?".zip";??????????????}??????????}??????????return?destParam;??????}?????????????????????private?static?void?createDestDirectoryIfNecessary(String?destParam)?{??????????File?destDir?=?null;??????????if?(destParam.endsWith(File.separator))?{??????????????destDir?=?new?File(destParam);??????????}?else?{??????????????destDir?=?new?File(destParam.substring(0,?destParam.lastIndexOf(File.separator)));??????????}??????????if?(!destDir.exists())?{??????????????destDir.mkdirs();??????????}??????}????????public?static?void?main(String[]?args)?{??????????zip("d:\\test\\cc",?"d:\\test\\cc.zip",?"11");??????????????????????}??}??
需要學習的東西太多,沒太多時間(或許只是借口)去研究它,上面的例子僅是簡單地解壓和壓縮操作;但在使用中可以發(fā)現(xiàn)Zip4J功能比較完備,如果需要更多地支持,那就真要好好去研究一下它,也許它真的不會使您失望。。。
補充
刪除壓縮文件中的目錄
看到有朋友在問如何刪除壓縮文件中的目錄,在這里補充一下。
利用zip4j刪除壓縮文件中的目錄,查閱API后很容易想到這樣的方式:
[java] view plaincopy
ZipFile?zipFile?=?new?ZipFile("d:\\FeiQ-V2.5.zip");??zipFile.setFileNameCharset("GBK");??zipFile.removeFile("sounds/");????????
但這種直接刪除壓縮文件中非空目錄的方式是不會成功的,你會看到zip文件絲毫沒有變化,雖然目錄對應(yīng)的FileHeader已被刪除(表現(xiàn)就是如果這時再將目錄下的所有文件刪除,則該目錄隨之消失) ;因此我們需要將該目錄下所有的文件都刪除掉,最后再將目錄刪除,根據(jù)這個思路,我們很容易形成如下的代碼:
[java] view plaincopy
void?removeDirFromZipArchive(String?file,?String?removeDir)?throws?ZipException?{????????????ZipFile?zipFile?=?new?ZipFile(file);??????zipFile.setFileNameCharset("GBK");??????????????????if?(!removeDir.endsWith(File.separator))?removeDir?+=?File.separator;??????????????FileHeader?dirHeader?=?zipFile.getFileHeader(removeDir);??????if?(null?==?dirHeader)?return;??????????????List?allHeaders?=?zipFile.getFileHeaders();??????for(int?i=0,?len?=?allHeaders.size();?i<len;?i++)?{??????????FileHeader?subHeader?=?(FileHeader)?allHeaders.get(i);??????????if?(subHeader.getFileName().startsWith(dirHeader.getFileName())??????????????????&&?!subHeader.getFileName().equals(dirHeader.getFileName()))?{??????????????zipFile.removeFile(subHeader);??????????}??????}????????????zipFile.removeFile(dirHeader);??}??
這樣仍然解決不了問題,如果你這樣做了,那么你將會得到一個java.lang.IndexOutOfBoundsException異常,那么看似正常的代碼為什么會報索引越界異常呢?其實我們通過zipFile.getFileHeaders()方法得到的List會隨遍歷中的刪除操作而發(fā)生變化,也就是說我們刪除了某個FileHeader,將會反映到該List中。每成功刪除一個FileHeader,List長度就減1,而i一直在0至List的初始長度之間遞增,反復(fù)幾次后就可能出現(xiàn)越界異常。
為了避免這種情況發(fā)生,我們可以多做一些操作,比如可以在遍歷中暫不進行刪除操作,而只是將要刪除的文件記錄下來,遍歷結(jié)束后再統(tǒng)一刪除,最后將目錄刪除,經(jīng)測試,這個思路可以解決問題。
簡單示例代碼:
[java] view plaincopy
void?removeDirFromZipArchive(String?file,?String?removeDir)?throws?ZipException?{????????????ZipFile?zipFile?=?new?ZipFile(file);??????zipFile.setFileNameCharset("GBK");??????????????????if?(!removeDir.endsWith(File.separator))?removeDir?+=?File.separator;??????????????????FileHeader?dirHeader?=?zipFile.getFileHeader(removeDir);??????if?(null?==?dirHeader)?return;??????????????List?headersList?=?zipFile.getFileHeaders();??????List<String>?removeHeaderNames?=?new?ArrayList<String>();??????for(int?i=0,?len?=?headersList.size();?i<len;?i++)?{??????????FileHeader?subHeader?=?(FileHeader)?headersList.get(i);??????????if?(subHeader.getFileName().startsWith(dirHeader.getFileName())??????????????????&&?!subHeader.getFileName().equals(dirHeader.getFileName()))?{??????????????removeHeaderNames.add(subHeader.getFileName());??????????}??????}????????????for(String?headerNameString?:?removeHeaderNames)?{??????????zipFile.removeFile(headerNameString);??????}??????zipFile.removeFile(dirHeader);??}?
總結(jié)
以上是生活随笔為你收集整理的zip4j -- Java处理zip压缩文件的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。