package com.cn;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.util.Enumeration;import java.util.zip.ZipEntry;import java.util.zip.ZipFile;import java.util.zip.ZipInputStream;import java.util.zip.ZipOutputStream;//錯誤小結://1 關於file.isFile()與file.isDirectory()記憶出了偏差.// 錯誤以為若是Directory一定是file,file不一定是Directory// 更正:file和Directory是兩碼事.只能是file或Directory中其中一個.// 要看的1 傳入一個路徑直接壓縮了.//2 血的教訓:// zip()方法中沒有關閉流zos.導致壓縮後的檔案解壓時出錯//重要總結://1 關於zip和unzip的核心操作對象是每一個檔案!!!// 比如碰到一個directory,那麼會去遍曆裡面的每一個檔案,挨個對其進行壓縮.// 不要錯誤地理解,若是一個directory,那麼會將其作為一個整體進行壓縮.//2 在JAVA中每一個壓縮檔都用一個ZipEntry表示// 所以在壓縮的過程中要得到每個檔案的完整路徑(從最外層檔案夾至檔案本身)// 用此完整路徑為每個壓縮檔new()一個ZipEntry//3 所以利用zipEntry可記錄原來的目錄層次.解壓後才保持原樣// 也可以看到在解壓時利用entrys.hasMoreElements()來挨個// 解壓每個zipEntrypublic class TestZipAndUnZip { public static void main(String[] args) throws Exception { TestZipAndUnZip test=new TestZipAndUnZip(); //將某一個檔案壓縮成zip// test.zip("E:\\", "aa\\1.txt", "E:\\cc1.zip"); //將某一個目錄壓縮成zip //test.zip("E:\\aa", "bb\\", "E:\\zz.zip");//right// // test.zip("E:\\", "aa", "E:\\zz678910.zip");//right//// //將某一個zip解壓// test.unZipFile("E:\\zz.zip", "E:\\zzzz"); /////////////////////以下正確/////////////////////////////// //壓縮和解壓單個檔案// test.zip2("E:\\aa\\1.txt","E:\\aaaaaaa\\aa1234.zip");// test.unZipFile2("E:\\aaaaaaa\\aa1234.zip", "E:\\aaaaaaa\\aaxixihaha"); //壓縮和解壓一個目錄 test.zip2("D:\\developmentTools","E:\\20.zip"); test.unZipFile2("E:\\20.zip", "E:\\555aaxx99xxx"); /////////////////////以上正確////////////////////////////// } /** * @param willZipDirPath 被壓縮檔(目錄)所在目錄 * @param willZipFileName 被壓縮檔(目錄)的名稱 * @param toFilePath 壓縮後檔案(目錄)名 */public void zip(String willZipDirPath, String willZipFileName, String zipedFileName) {System.out.println("…………………以下為zip()方法…………………………");if (willZipDirPath == null) {return;}File willZipDir = new File(willZipDirPath);if (!willZipDir.exists() || !willZipDir.isDirectory()) {return;}// 獲得目錄絕對路徑String willZipDirAbsolutePath = willZipDir.getAbsolutePath();System.out.println("willZipDir.getAbsolutePath()="+willZipDirAbsolutePath);//壓縮後的檔案File zipedFile = new File(zipedFileName);try {//從壓縮後的檔案得到壓縮輸出資料流ZipOutputStream//這裡的zos只指向了壓縮後檔案的最外層.那麼它怎麼//維持了原來的目錄結構呢?//就是利用了ZipEntry!!!//在fileToZip()方法中就可以看到ZipEntry的使用!!ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipedFile));if (willZipFileName.equals("*")) {//若傳入的是*表示將此路徑下所有東西都要壓縮//所以調用dirToZip()dirToZip(willZipDirAbsolutePath, willZipDir, zos);} else {//將被壓縮的檔案File willZipFile = new File(willZipDirPath, willZipFileName);System.out.println("ccccccccccc name="+willZipFile.getName());System.out.println("ccccccccccc getAbsolutePath="+willZipFile.getAbsolutePath());if (willZipFile.isFile()) {System.out.println("…………………最外層開始壓縮檔………………………");fileToZip(willZipDirPath, willZipFile, zos);System.out.println("…………………最外層壓縮檔結束………………………");}if (willZipFile.isDirectory()) {System.out.println("…………………最外層開始壓縮目錄………………………");dirToZip(willZipDirPath, willZipFile, zos);System.out.println("…………………最外層壓縮目錄結束………………………");}// 關閉流!!!zos.close();System.out.println("…………………以上為zip()方法…………………………");}} catch (Exception e) {// TODO: handle exception}} /** * @param dirPath 被壓縮檔所在目錄 * @param willZipFile 被壓縮檔的名稱 * @param zos 輸出資料流 */public void fileToZip(String dirPath, File willZipFile,ZipOutputStream zos){ FileInputStream fis=null; ZipEntry zipEntry=null; byte [] buffer=new byte[1024*8]; int len=0; if (willZipFile.isFile()) {try {fis=new FileInputStream(willZipFile);zipEntry=new ZipEntry(getEntryName(dirPath, willZipFile));zos.putNextEntry(zipEntry);System.out.println("…………………以下為fileToZip()方法…………………………");System.out.println("zipEntry.getName="+zipEntry.getName());System.out.println("zipEntry.isDirectory="+zipEntry.isDirectory());System.out.println("zipEntry.getSize="+zipEntry.getSize());System.out.println("zipEntry.getTime="+zipEntry.getTime());System.out.println("zipEntry.getComment="+zipEntry.getComment());System.out.println("…………………以上為fileToZip()方法…………………………");while((len=fis.read(buffer))!=-1){zos.write(buffer, 0, len);}zos.closeEntry();fis.close();} catch (Exception e) {}} }/** * @param dirPath 被壓縮目錄所在的上級目錄 * @param willZipDir 被壓縮目錄 * @param zos 輸出資料流 */public void dirToZip(String dirPath, File willZipDir, ZipOutputStream zos) {if (willZipDir.isDirectory()) {File[] files = willZipDir.listFiles();//處理-->該檔案夾下無檔案 if (files.length==0) {ZipEntry zipEntry=new ZipEntry(getEntryName(dirPath, willZipDir));try {zos.putNextEntry(zipEntry);zos.closeEntry();} catch (Exception e) {e.printStackTrace();}return;} //處理-->該檔案夾下的所有檔案 for (int i = 0; i < files.length; i++) {File file = files[i];//若是檔案,遞迴調用fileToZip()if (file.isFile()) {System.out.println("xxxxxxxxxx內層開始fileToZip()方法xxxxxxxxxx");fileToZip(dirPath, file, zos);System.out.println("xxxxxxxxxx內層fileToZip()方法結束xxxxxxxxxx");}//若是檔案,遞迴調用dirToZip()if (file.isDirectory()) {System.out.println("xxxxxxxxxx內層開始dirToZip()方法xxxxxxxxxx");dirToZip(dirPath, file, zos);System.out.println("xxxxxxxxxx內層dirToZip()方法結束xxxxxxxxxx");}}}} /** * @param dirPath 將被壓縮檔所在目錄 * @param willZipFile 將被壓縮的檔案 * @return *///產生的是每個檔案的完整路徑(從最外層檔案夾至檔案本身)//這樣產生的zipEntry就記錄了原來的目錄層次.解壓後才保持原樣public String getEntryName(String dirPath, File willZipFile) {if (!dirPath.endsWith(File.separator)) {dirPath += File.separator;}String willZipFilePath=willZipFile.getAbsolutePath();if (willZipFile.isDirectory()) {willZipFilePath+="/";}int index=willZipFilePath.indexOf(dirPath);System.out.println("xx返回的 entryName="+ willZipFilePath.substring(index+dirPath.length()));return willZipFilePath.substring(index+dirPath.length());}/** * @param zipedFileName 待解壓zip檔案 * @param unzipDirPath 檔案解壓後的最外層檔案名稱 * @throws IOException */public void unZipFile(String zipedFileName,String unzipDirPath) throws Exception{if (!unzipDirPath.endsWith(File.separator)) {unzipDirPath+=File.separator;}try {ZipFile zipedFile=new ZipFile(zipedFileName);ZipEntry zipEntry=null;String entryName=null;String unzipedFileName=null;Enumeration entrys=zipedFile.entries();byte [] buffer=new byte[1024*8];int len=0;while (entrys.hasMoreElements()) {zipEntry=(ZipEntry) entrys.nextElement();entryName=zipEntry.getName();unzipedFileName=unzipDirPath+entryName;System.out.println("…………………以下為unZipFile()方法…………………………");System.out.println("zipedFileName="+zipedFileName);System.out.println("unzipDirPath="+unzipDirPath);System.out.println("entryName="+entryName);System.out.println("unzipedFileName="+unzipedFileName);System.out.println("…………………以上為unZipFile()方法…………………………");if (zipEntry.isDirectory()) {//沒有執行此代碼new File(unzipedFileName).mkdirs();} else {//總是執行該代碼.因為壓縮的時候是對每個檔案進行壓縮的. new File(unzipedFileName).getParentFile().mkdirs();}File unzipedFile=new File(unzipedFileName);FileOutputStream fos=new FileOutputStream(unzipedFile);InputStream is=zipedFile.getInputStream(zipEntry);while ((len=is.read(buffer))!=-1) {fos.write(buffer, 0, len);}fos.close();is.close();}} catch (Exception e) {e.printStackTrace();}}//////////////////////////////////////////////////////////////////////////////////////** * 該方法將一個給定路徑的檔案壓縮 * @param willZipPath 將要壓縮的檔案的路徑 * @param zipedPath 該檔案壓縮後的路徑 */public void zip2(String willZipPath,String zipedPath){try {File willZipedFile=new File(willZipPath);File zipedFile=new File(zipedPath);ZipOutputStream zos=new ZipOutputStream(new FileOutputStream(zipedFile));if (willZipedFile.isFile()) {fileToZip2(willZipPath,willZipedFile, zos);}if (willZipedFile.isDirectory()) {dirToZip2(willZipPath,willZipedFile, zos);}//方法調用完成後關閉流zos.close();} catch (Exception e) {// TODO: handle exception}}/** * @param rawPath * @param willZipedFile * @param zos */ //test.zip2("E:\\aa\\1.txt","E:\\aaaaaaa\\aa1234.zip");public void fileToZip2(String rawPath,File willZipedFile,ZipOutputStream zos){try {//執行個體化一個名稱為ab.txt的ZipEntry對象File file=new File(rawPath);ZipEntry entry = new ZipEntry(getEntryName2(rawPath, file));//把產生的ZipEntry對象加入到壓縮檔中//而之後往壓縮檔中寫入的內容都會放在這個ZipEntry對象裡面zos.putNextEntry(entry);InputStream is = new FileInputStream(rawPath);int len = 0;while ((len = is.read()) != -1){zos.write(len);}is.close();//流關閉錯誤了!!//zos.close();} catch (Exception e) {}}/** * @param rawPath 原檔案所在路徑 * @param zipedFile 壓縮後的檔案 * @param zos */public void dirToZip2(String rawPath,File zipedFile, ZipOutputStream zos) {if (zipedFile.isDirectory()) {File[] files = zipedFile.listFiles();//處理-->該檔案夾下無檔案// if (files.length==0) {////ZipEntry zipEntry=new ZipEntry(getEntryName(dirPath, willZipDir));//ZipEntry zipEntry=new ZipEntry("");//try {//zos.putNextEntry(zipEntry);//zos.closeEntry();//} catch (Exception e) {//e.printStackTrace();//}//return;//} for (int i = 0; i < files.length; i++) {File file = files[i];//若是檔案,遞迴調用fileToZip()if (file.isFile()) {fileToZip2(file.getAbsolutePath(),file, zos);}//若是檔案,遞迴調用dirToZip()if (file.isDirectory()) {dirToZip2(file.getAbsolutePath(),file, zos);}}}}/** * @param rawPath 需要壓縮的目錄或者檔案的完整路徑 * @param file 需要壓縮的檔案 * @return entryName */public String getEntryName2(String rawPath,File file){//file是rawPath對應的filetry {String rawDir=rawPath.substring(3);int rawDirIndex=file.getAbsolutePath().indexOf(rawDir);String entryName=file.getAbsolutePath().substring(rawDirIndex);return entryName;} catch (Exception e) {}return null;}/** * @param zipedFilePath 原壓縮檔的路徑 * @param unzipPath 檔案解壓後的路徑 */public void unZipFile2(String zipedFilePath, String unzipPath){try {//解壓後的最外層檔案夾File unzipFile=new File(unzipPath);if (!unzipFile.exists()) {unzipFile.mkdirs();}File zipedFile = new File(zipedFilePath);File perUnzipedFile = null;// 執行個體化ZipFile對象 這個很容易錯!!!!// ZipFile zipFile = new ZipFile(file) ;ZipInputStream zis = new ZipInputStream(new FileInputStream(zipedFile));FileOutputStream fos = null; ZipEntry entry = null; while ((entry = zis.getNextEntry()) != null) { // 得到一個壓縮實體perUnzipedFile = new File(unzipPath+File.separator+entry.getName());if (!perUnzipedFile.getParentFile().exists()) { perUnzipedFile.getParentFile().mkdirs(); // 建立父目錄}if (!perUnzipedFile.exists()) { // 判斷輸出檔案是否存在perUnzipedFile.createNewFile(); // 建立檔案}// 得到每一個實體的輸入資料流fos = new FileOutputStream(perUnzipedFile); int len = 0;while ((len = zis.read()) != -1) {fos.write(len);}}zis.close(); fos.close(); } catch (Exception e) {// TODO: handle exception}}}