Java檔案壓縮與解壓縮(三)

來源:互聯網
上載者:User
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.ZipOutputStream;//錯誤小結://1 關於file.isFile()與file.isDirectory()記憶出了偏差.//  錯誤以為若是Directory一定是file,file不一定是Directory//  更正:file和Directory是兩碼事.只能是file或Directory中其中一個.//  要看的1 傳入一個路徑直接壓縮了.//2 並不是說我們執行一句File f=new File("F:\\x.txt");//  在本地硬碟上就產生了一個x.txt檔案.而應該進行如下的//  操作才可以.//  File f=new File("F:\\x.txt");//  if (!f.exists()) {//   f.createNewFile();//  }// 其中f.createNewFile()表示建立了一個空檔案//// 多數的情況下,我們執行了File f=new File("F:\\x.txt")// 以後再利用輸入資料流,輸出資料流對f進行操作,比如往該x.txt檔案中// 寫入hello world// //3 血的教訓://  zip()方法中沒有關閉流zos.導致壓縮後的檔案解壓時出錯//重要總結://1 關於zip和unzip的核心操作對象是每一個檔案!!!//  比如碰到一個directory,那麼會去遍曆裡面的每一個檔案,挨個對其進行壓縮.//  不要錯誤地理解,若是一個directory,那麼會將其作為一個整體進行壓縮.//2 在JAVA中每一個壓縮檔都用一個ZipEntry表示//  所以在壓縮的過程中要得到每個檔案的完整路徑(從最外層檔案夾至檔案本身)//  用此完整路徑為每個壓縮檔new()一個ZipEntry//3 所以利用zipEntry可記錄原來的目錄層次.解壓後才保持原樣//  也可以看到在解壓時利用entrys.hasMoreElements()來挨個//  解壓每個zipEntry.//  參見解壓中的代碼://  new File(unzipPath+File.separator+entry.getName());public 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("F:\\", "kk", "F:\\zz678910.zip");//right//////   //將某一個zip解壓//   test.unZipFile("F:\\zz678910.zip", "E:\\zzzz");         /////////////////////以下正確///////////////////////////////   //壓縮和解壓單個檔案   test.zip2("F:\\kk\\cc.txt","F:\\88.zip");   test.unZipFile2("F:\\88.zip", "F:\\abc");      //壓縮和解壓一個目錄   test.zip2("F:\\kk","F:\\9zip.zip");   test.unZipFile2("F:\\9zip.zip", "F:\\9files");      /////////////////////以上正確//////////////////////////////   }   /** * @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));System.out.println("xxxxxxxxxxxxxxxx "+zipEntry.getName());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()) {//沒有執行此代碼System.out.println("999999999999");new File(unzipedFileName).mkdirs();} else {//總是執行該代碼.因為壓縮的時候是對每個檔案進行壓縮的.                    new File(unzipedFileName).getParentFile().mkdirs();}FileOutputStream fos=null;InputStream is=null;File unzipedFile=new File(unzipedFileName);if (unzipedFile.isDirectory()) {File [] files=unzipedFile.listFiles();for (int i = 0; i < files.length; i++) {File file = files[i]; fos=new FileOutputStream(file); is=zipedFile.getInputStream(zipEntry);while ((len=is.read(buffer))!=-1) {fos.write(buffer, 0, len);}}}else{ fos=new FileOutputStream(unzipedFile); 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 willZipFile = new File(willZipPath);File zipedFile = new File(zipedPath);ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipedFile));if (willZipFile.isFile()) {fileToZip2(willZipPath, zos);}if (willZipFile.isDirectory()) {dirToZip2(willZipPath, willZipFile, zos);}// 方法調用完成後關閉流zos.close();} catch (Exception e) {// TODO: handle exception}}/** * @param willZipFilePath  待壓縮檔的路徑 * @param zos              壓縮檔輸出資料流 * 1 關於以下兩句代碼 * ZipEntry entry = new ZipEntry(); * zos.putNextEntry(entry); * 把產生的ZipEntry對象加入到壓縮檔中 * 之後往壓縮檔中寫入的內容均放在該ZipEntry對象中 *  * 2 fis.close()但是不能在此處zos.close() * 因為該zos是上一方法傳遞過來的.可能在壓縮目錄的時候會 * 再次使用到該zos流.若此時關閉,則導致目錄中的一個檔案 * 被壓縮 */public void fileToZip2(String willZipFilePath,ZipOutputStream zos){try {File willZipFile=new File(willZipFilePath);ZipEntry entry = new ZipEntry(getEntryName2(willZipFilePath, willZipFile));zos.putNextEntry(entry);FileInputStream fis = new FileInputStream(willZipFilePath);int len = 0;while ((len = fis.read()) != -1){zos.write(len);}fis.close();//流關閉錯誤!//zos.close();} catch (Exception e) {}}/** * @param willZipDirctoryPath   原目錄所在路徑 * @param willZipedDirectory    原目錄 * @param zos                   壓縮流 * 注意: * 在處理空檔案夾的時候 * getEntryName2(willZipDirctoryPath, willZipedDirectory)+"/" * 中的"/"是比不可少的 */public void dirToZip2(String willZipDirctoryPath,File willZipedDirectory, ZipOutputStream zos) {if (willZipedDirectory.isDirectory()) {File[] files = willZipedDirectory.listFiles();//處理空檔案夾的情況            if (files.length==0) {ZipEntry zipEntry=new ZipEntry(getEntryName2(willZipDirctoryPath, willZipedDirectory)+"/");try {zos.putNextEntry(zipEntry);} 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(), zos);}//若是檔案,遞迴調用dirToZip()if (file.isDirectory()) {dirToZip2(file.getAbsolutePath(),file, zos);}}}}/** * @param rawPath  需要壓縮的目錄或者檔案的完整路徑 * @param file     需要壓縮的檔案或者目錄 * @return         entryName *  * 該方法返回EntryName,表示從最外層目錄開始到該檔案(目錄) * 的完整路徑 * 備忘: * 1 該樣本中檔案均存放在某盤下,如E:\所以rawPath.substring(3); * 2 注釋中"@param file 需要壓縮的檔案或者目錄".其實絕大多數情況下 *  都是檔案,只有一種情況是目錄,就是空檔案夾的情況.  */public String getEntryName2(String rawPath,File file){try {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      檔案解壓後的路徑 * 對於檔案或者目錄操作的小梳理: * 1 對於目錄應該先執行file.mkdir(s)()才可以 *  往裡面其下存入檔案.比如: *  File f=new File("F:\\test\\x.txt");if (!f.exists()) {f.createNewFile();}這當然要報錯,因為x.txt的所在目錄還不存在!!所以應該改正為:File f=new File("F:\\test\\x.txt");f.getParentFile().mkdirs();if (!f.exists()) {f.createNewFile();}2同樣的道理File f=new File("F:\\test\\x.txt");if (f.isFile()) {System.out.println("true");}else{System.out.println("false");}結果為false3類似的問題File f=new File("F:\\x.txt");if (f.isFile()) {System.out.println("true");}else{System.out.println("false");}結果為false因為只是new了一個File,並沒有建立!!!File f=new File("F:\\x.txt");f.createNewFile();if (f.isFile()) {System.out.println("true");}else{System.out.println("false");}此時為true此處:if (zipEntry.isDirectory()) {    new File(perUnzipFilePath).mkdirs();} else {new File(perUnzipFilePath).getParentFile().mkdirs();}已經建立了每個檔案夾.然後才開始對每個空檔案夾和每個檔案進行流操作.和上面的道理一致,剛開始犯了個錯誤,沒有採用else {fos = new FileOutputStream(perUnzipFile);is = zipFile.getInputStream(zipEntry);while ((len = is.read(buffer)) != -1) {fos.write(buffer, 0, len);}}而是用if(perUnzipFile.isFile()){}來操作,這當然錯了.因為該perUnzipFile沒有執行perUnzipFile.createNewFile();所以它還不是File.類似的情況,多採用流操作來進行讀寫.所以總結兩種與File有關的操作:1 File f=new File("");  f.createNewFile();     然後對f操作2 file f=new File("");    然後用輸入輸出資料流進行流操作    舉例子:  File f=new File("F:\\2221x.txt");      FileOutputStream fos=new FileOutputStream(f);  String string="hello";  byte []b=string.getBytes();  fos.write(b, 0, b.length);     該例子是正確的.     疑問:沒有執行 f.createNewFile()為什麼不報錯.因為輸出資料流  FileOutputStream已經幫我們做了該工作了.修改例子即可知:File f=new File("F:\\2221x.txt");if (f.isFile()) {System.out.println("true1");} else {System.out.println("false1");}FileOutputStream fos=new FileOutputStream(f);if (f.isFile()) {System.out.println("true2");} else {System.out.println("false2");}String string="hello";byte []b=string.getBytes();fos.write(b, 0, b.length);輸出false1,true2這就得到了驗證. */public void unZipFile2(String zipedFilePath, String unzipPath) {FileOutputStream fos=null;InputStream is=null;ZipEntry zipEntry=null;String perUnzipFilePath=null;if (!unzipPath.endsWith(File.separator)) {unzipPath+=File.separator;}try {ZipFile zipFile=new ZipFile(zipedFilePath);Enumeration entries=zipFile.entries();byte [] buffer=new byte[1024*8];int len=0;while (entries.hasMoreElements()) {zipEntry = (ZipEntry) entries.nextElement();perUnzipFilePath = unzipPath + zipEntry.getName();//1建立每個檔案夾if (zipEntry.isDirectory()) {//處理空檔案夾的情況//建立空目錄new File(perUnzipFilePath).mkdirs();} else {//為每個檔案創立其所在目錄new File(perUnzipFilePath).getParentFile().mkdirs();}                //2在用流操作處理每個檔案夾中的檔案// 2.1if中的操作只是針對空目錄而進行的.所以if中的代碼可以// 注釋掉,無實際意義.// 2.2else中的操作是對於每個具體的檔案而進行的流操作File perUnzipFile = new File(perUnzipFilePath);if (perUnzipFile.isDirectory()) {File[] files = perUnzipFile.listFiles();for (int i = 0; i < files.length; i++) {File file = files[i];fos = new FileOutputStream(file);is = zipFile.getInputStream(zipEntry);while ((len = is.read(buffer)) != -1) {fos.write(buffer, 0, len);}}} else {fos = new FileOutputStream(perUnzipFile);is = zipFile.getInputStream(zipEntry);while ((len = is.read(buffer)) != -1) {fos.write(buffer, 0, len);}}}if (fos!=null) {fos.close();}if (is!=null) {is.close();}} catch (Exception e) {e.printStackTrace();}}}

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.