zip文件壓縮


zip文件結構
     
     上面中的每一行都是一個條目, zip文件就是由一個或者多個條目組成。
     條目在Java中對應ZipEntry類
     

創建zip壓縮文件
     知道了zip文件結構之后,大概就知道怎么去創建一個zip壓縮文件了。
     之前,先了解下創建普通的文件都是經過以下幾個步驟:
     1、創建文件輸出流FileOutputStream fout = new FileOutputStream(new File("XXX"));
     2、往文件輸出流中寫入文件內容,fout.write(XXX);
     3、關閉輸出流fout.close();
     這樣,一個普通的創建就是生成了

     既然zip壓縮文件也是文件,那么它的創建也基本都差不多,只是,zip文件結構跟普通文件有點差別,因為它里面是由條目(ZipEntry)組成的。
     所以創建zip壓縮文件的步驟如下:
     1、創建zip壓縮文件輸出流
           ZipOutputStream zos = new ZipOutputStream( new FileOutputStream(new File("XXX")) );

     2、創建zip文件條目
           ZipEntry entry = new ZipEntry(name)
           備注:name指定條目的名稱,例如上圖顯示的client.cer,這里name可以帶路徑,例如:a/b/c/test.txt,這樣就是創建a/b/c這個目錄。

     3、將條目添加到zip文件輸出流
          zos.putNextEntry(entry);
     
     4、創建被文件的輸入流,讀取文件內容,並寫入到zip壓縮文件輸出流。這個時候,寫入的內容都屬於當前這個條目的。
          FileInputStream in =  new  FileInputStream( new File("XXX") );
     byte[]buffer = new byte[1024];
     int len = 0;
     while((len = in.read(buffer))!=-1){
          zos.write(buffer ,0 ,len);
     }
     in.close();

     
     5、關閉zip文件輸出流
         zos.close()


zip亂碼問題解決
       使用Apache中的 org.apache.tools.zip.ZipOutputStream類來替換Java自帶的ZipOutputStream類
        FileOutputStream fout =  new  FileOutputStream( "f:\\abc.zip" );
    ZipOutputStream out = new ZipOutputStream(fout);
    out.setEncoding("utf-8"); //這條語句時必須的,否則,生成中文條目時,無法打開zip文件或者出現亂碼
    ZipEntry entry = new ZipEntry("測試文件.txt");
    out.putNextEntry(entry);

誤解區:
    以前都是以為一個文件或者目錄就對應zip文件中的一個條目,其實並非一定是這樣的。解析如下:
    zip文件是以條目來組織,操作zip文件都是基於條目來進行的,因此,每次往條目新增內容時,
    得首先創建zip文件條目,並將添加到zip文件輸出,之后,zip輸出流,才認為之后寫入到輸出流中的
    內容都是屬於這個條目,直到zip輸出流中新增新的條目。不過一般來正常來說,都是一個文件或者目錄就對應zip文件中的一個條目。
    
    正常情況下,一個文件或者目錄對應一個條目,如下圖:
    
       
       但是也可以將a.txt、b.txt的內容都只寫入的一個條目c.txt
       

       生成的zip文件結果圖:
       
       這里可以發現,只要沒有重新往zip文件輸出流中添加新的條目,那么,所有的內容都是寫入當前條目中。


自己封裝的一個zip壓縮工具類
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class FilleUtils {
    
    
    /**
     * zip壓縮文件,默認生成的壓縮文件目錄與當前需要壓縮的文件或者目錄同級
     * @param filePath  需要壓縮的文件或者目錄
     * @return 返回zip壓縮文件路徑
     */
    public static String zip(String filePath) throws Exception{
         System.out.println("壓縮中..."); 
         String zipFilePath = null;
         File srcFile = new File(filePath);
         
         //獲得zip文件路徑
         if(srcFile.isDirectory()){
             zipFilePath = srcFile.getParent() + srcFile.getName() + ".zip";
         }
         else{
             String zipFileName = "";
             if(srcFile.getName().indexOf(".")>-1)
                 zipFileName = srcFile.getName().substring(0 ,srcFile.getName().lastIndexOf(".")) + ".zip";
             else
                 zipFileName = srcFile.getName() + ".zip";
             zipFilePath = srcFile.getParent() + zipFileName;
         }
         
         //開始進行壓縮
         ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFilePath));   
         BufferedOutputStream bo = new BufferedOutputStream(out);  
         zip(out, srcFile, srcFile.getName(), bo);  
         bo.close();  
         out.close(); 
         System.out.println("壓縮完成");  
         
         return zipFilePath;
    }
    
    
    /**
     * zip壓縮文件
     * @param filePath
     * @param zipFilePath
     */
    public static void zip(String filePath ,String zipFilePath) throws Exception{
         System.out.println("壓縮中..."); 
         File srcFile = new File(filePath);
         
         //檢查壓縮文件路徑是否存在,不存在則創建
         File zipFile = new File(zipFilePath);
         if(!zipFile.exists()){
             zipFile.getParentFile().mkdirs();
         }
         
         //開始壓縮
         ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFilePath));   
         BufferedOutputStream bo = new BufferedOutputStream(out);  
         zip(out, srcFile, srcFile.getName(), bo);  
         bo.close();  
         out.close();  
         System.out.println("壓縮完成");  
    }
    
    
    
    /**
     * 壓縮指定的多個文件或者目錄
     * @param filePathList
     * @param zipFilePath
     * @throws Exception
     */
    public static void zip(ArrayList<String> filePathList , String zipFilePath) throws Exception{
         System.out.println("壓縮中...");
         //檢查壓縮文件路徑是否存在,不存在則創建
         File zipFile = new File(zipFilePath);
         if(!zipFile.exists()){
             zipFile.getParentFile().mkdirs();
         }
        
         //開始壓縮
         ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFilePath));  
         BufferedOutputStream bo = new BufferedOutputStream(out); 
         if(filePathList==null || filePathList.size()==0){
             throw new RuntimeException("沒有指定需要壓縮的文件");
         }
         for(String filePath :filePathList){
             File srcFile = new File(filePath);
             zip(out, srcFile, srcFile.getName(), bo); 
         }
         bo.close();  
         out.close(); 
         System.out.println("壓縮完成"); 
    }
    
    
    
    private static void zip(ZipOutputStream out , File srcFile ,String base ,BufferedOutputStream bo) throws Exception{
        
        //如果需要壓縮的文件是目錄,則進行遞歸壓縮處理
        if(srcFile.isDirectory()){
            File[] fileList = srcFile.listFiles();  
            
            //如果是空目錄,也需要將該目錄壓縮進去,注意,此時zipentry的name必須以“/"結束
            if (fileList.length == 0) {  
                out.putNextEntry(new ZipEntry(base + "/")); // 創建zip壓縮進入點base  
                out.closeEntry();
            }  
            for (int i = 0; i < fileList.length; i++) {  
                zip(out, fileList[i], base + "/" + fileList[i].getName(), bo); // 遞歸遍歷子文件夾  
            } 
        }
        else{
            out.putNextEntry(new ZipEntry(base)); // 創建zip壓縮進入點base  
            FileInputStream in = new FileInputStream(srcFile);  
             byte []buffer =  new   byte [1024];
            int len = 0;
            while((len = in.read(buffer))!=-1){
                out.write(buffer ,0 ,len);
            }   
            in.close(); // 輸入流關閉 
        }
    } 

} 









免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM