壓縮和解壓的工具類(ant-1.8.4.jar) – JAVA編程語言程序開發技術文章

使用ant-1.8.4.jar中的org.apache.tools.zip包進行文件的文件壓縮和解壓,主要使用該jar包中的以下類:
org.apache.tools.zip.ZipEntry;
org.apache.tools.zip.ZipFile;
org.apache.tools.zip.ZipOutputStream;
 下面是我寫的壓縮和解壓文件的工具類,並附測試,請大傢為我debug:
[java] 
import java.io.BufferedInputStream; 
import java.io.BufferedOutputStream; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.util.ArrayList; 
import java.util.Enumeration; 
import java.util.List; 
import java.util.zip.CRC32; 
import java.util.zip.CheckedOutputStream; 
import java.util.zip.Deflater; 
import java.util.zip.ZipException; 
 
import org.apache.tools.zip.ZipEntry; 
import org.apache.tools.zip.ZipFile; 
import org.apache.tools.zip.ZipOutputStream; 
 
/**
  * @Description: 
  *     壓縮和解壓工具
 */ 
public class ZipUtil { 
 
    /**
      * @Description: 
      *     壓縮文件
      * @param sourcePath 將要壓縮的文件或目錄的路徑,請使用絕對路徑
      * @param zipPath 生成壓縮文件的路徑,請使用絕對路徑。如果該路徑以“.zip”為結尾,
      *         則壓縮文件的名稱為此路徑;如果該路徑不以“.zip”為結尾,則壓縮文件的名稱
      *         為該路徑加上將要壓縮的文件或目錄的名稱,再加上以“.zip”結尾
      * @param encoding 壓縮編碼
      * @param comment 壓縮註釋
     */ 
    public static void compress(String sourcePath, String zipPath, String encoding, String comment) 
            throws FileNotFoundException, IOException { 
        // 判斷要壓縮的文件是否存在 
        File sourceFile = new File(sourcePath); 
        if (!sourceFile.exists() || (sourceFile.isDirectory() && sourceFile.list().length == 0)) { 
            throw new FileNotFoundException("要壓縮的文件或目錄不存在,或者要壓縮的目錄為空"); 
        } 
        // 設置壓縮文件路徑,默認為將要壓縮的路徑的父目錄為壓縮文件的父目錄 
        if (zipPath == null || "".equals(zipPath)) { 
            String sourcePathName = sourceFile.getAbsolutePath(); 
            int index = sourcePathName.lastIndexOf("."); 
            zipPath = (index > -1 ? sourcePathName.substring(0, index) : sourcePathName) + ".zip"; 
        } else { 
            // 如果壓縮路徑為目錄,則將要壓縮的文件或目錄名做為壓縮文件的名字,這裡壓縮路徑不以“.zip”為結尾則認為壓縮路徑為目錄 
            if(!zipPath.endsWith(".zip")){ 
                // 如果將要壓縮的路徑為目錄,則以此目錄名為壓縮文件名;如果將要壓縮的路徑為文件,則以此文件名(去除擴展名)為壓縮文件名 
                String fileName = sourceFile.getName(); 
                int index = fileName.lastIndexOf("."); 
                zipPath = zipPath + File.separator + (index > -1 ? fileName.substring(0, index) : fileName) + ".zip"; 
            } 
        } 
        // 設置解壓編碼 
        if (encoding == null || "".equals(encoding)) { 
            encoding = "GBK"; 
        } 
        // 要創建的壓縮文件的父目錄不存在,則創建 
        File zipFile = new File(zipPath); 
        if (!zipFile.getParentFile().exists()) { 
            zipFile.getParentFile().mkdirs(); 
        } 
        // 創建壓縮文件輸出流 
        FileOutputStream fos = null; 
        try { 
            fos = new FileOutputStream(zipPath); 
        } catch (FileNotFoundException e) { 
            if (fos != null) { 
                try{ fos.close(); } catch (Exception e1) {} 
            } 
        } 
        // 使用指定校驗和創建輸出流 
        CheckedOutputStream csum = new CheckedOutputStream(fos, new CRC32()); 
        // 創建壓縮流 
        ZipOutputStream zos = new ZipOutputStream(csum); 
        // 設置編碼,支持中文 
        zos.setEncoding(encoding); 
        // 設置壓縮包註釋 
        zos.setComment(comment); 
        // 啟用壓縮 
        zos.setMethod(ZipOutputStream.DEFLATED); 
        // 設置壓縮級別為最強壓縮 
        zos.setLevel(Deflater.BEST_COMPRESSION); 
        // 壓縮文件緩沖流 
        BufferedOutputStream bout = null; 
        try { 
            // 封裝壓縮流為緩沖流 
            bout = new BufferedOutputStream(zos); 
            // 對數據源進行壓縮 
            compressRecursive(zos, bout, sourceFile, sourceFile.getParent()); 
        } finally { 
            if (bout != null) { 
                try{ bout.close(); } catch (Exception e) {} 
            } 
        } 
    } 
 
    /**
      * @Description: 
      *     壓縮文件,支持將多個文件或目錄壓縮到同一個壓縮文件中
      * @param sourcePath 將要壓縮的文件或目錄的路徑的集合,請使用絕對路徑
      * @param zipPath 生成壓縮文件的路徑,請使用絕對路徑。該路不能為空,並且必須以“.zip”為結尾
      * @param encoding 壓縮編碼
      * @param comment 壓縮註釋
     */ 
    public static void compress(List<String> sourcePaths, String zipPath, String encoding, String comment) 
            throws FileNotFoundException, IOException { 
        // 設置壓縮文件路徑,默認為將要壓縮的路徑的父目錄為壓縮文件的父目錄 
        if (zipPath == null || "".equals(zipPath) || !zipPath.endsWith(".zip")) { 
            throw new FileNotFoundException("必須指定一個壓縮路徑,而且該路徑必須以'.zip'為結尾"); 
        } 
        // 設置解壓編碼 
        if (encoding == null || "".equals(encoding)) { 
            encoding = "GBK"; 
        } 
        // 要創建的壓縮文件的父目錄不存在,則創建 
        File zipFile = new File(zipPath); 
        if (!zipFile.getParentFile().exists()) { 
            zipFile.getParentFile().mkdirs(); 
        } 
        // 創建壓縮文件輸出流 
        FileOutputStream fos = null; 
        try { 
            fos = new FileOutputStream(zipPath); 
        } catch (FileNotFoundException e) { 
            if (fos != null) { 
                try{ fos.close(); } catch (Exception e1) {} 
            } 
        } 
        // 使用指定校驗和創建輸出流 
        CheckedOutputStream csum = new CheckedOutputStream(fos, new CRC32()); 
        // 創建壓縮流 
        ZipOutputStream zos = new ZipOutputStream(csum); 
        // 設置編碼,支持中文 
        zos.setEncoding(encoding); 
        // 設置壓縮包註釋 
        zos.setComment(comment); 
        // 啟用壓縮 
        zos.setMethod(ZipOutputStream.DEFLATED); 
        // 設置壓縮級別為最強壓縮 
        zos.setLevel(Deflater.BEST_COMPRESSION); 
        // 壓縮文件緩沖流 
        BufferedOutputStream bout = null; 
        try { 
            // 封裝壓縮流為緩沖流 
            bout = new BufferedOutputStream(zos); 
            // 迭代壓縮每一個路徑 
            for (int i=0,len=sourcePaths.size(); i<len; i++) { 
                // 獲取每一個壓縮路徑 
                File sourceFile = new File(sourcePaths.get(i)); 
                // 對數據源進行壓縮 
                compressRecursive(zos, bout, sourceFile, sourceFile.getParent()); 
            } 
        } finally { 
            if (bout != null) { 
                try{ bout.close(); } catch (Exception e) {} 
            } 
        } 
    } 
     
    /**
      * @Description: 
      *     壓縮文件時,所使用的迭代方法
      * @param zos 壓縮輸出流
      * @param bout 封裝壓縮輸出流的緩沖流
      * @param sourceFile 將要壓縮的文件或目錄的路徑
      * @param prefixDir 整個將要壓縮的文件或目錄的父目錄,傳入此值為瞭獲取壓縮條目的名稱
     */ 
    private static void compressRecursive(ZipOutputStream zos, BufferedOutputStream bout, 
            File sourceFile, String prefixDir) throws IOException, FileNotFoundException { 
        // 獲取壓縮條目名,初始時將要壓縮的文件或目錄的相對路徑 
        String entryName = sourceFile.getAbsolutePath().substring(prefixDir.length() + File.separator.length()); 
        // 判斷是文件還是目錄,如果是目錄,則繼續迭代壓縮 
        if (sourceFile.isDirectory()) { 
            // 如果是目錄,則需要在目錄後面加上分隔符('/') 
            //ZipEntry zipEntry = new ZipEntry(entryName + File.separator); 
            //zos.putNextEntry(zipEntry); 
            // 獲取目錄中的文件,然後迭代壓縮 
            File[] srcFiles = sourceFile.listFiles(); 
            for (int i = 0; i < srcFiles.length; i++) { 
                // 壓縮 
                compressRecursive(zos, bout, srcFiles[i], prefixDir); 
            } 
        } else { 
            // 開始寫入新的ZIP文件條目並將流定位到條目數據的開始處 
            ZipEntry zipEntry = new ZipEntry(entryName); 
            // 向壓縮流中寫入一個新的條目 
            zos.putNextEntry(zipEntry); 
            // 讀取將要壓縮的文件的輸入流 
            BufferedInputStream bin = null; 
            try{ 
                // 獲取輸入流讀取文件 
                bin = new BufferedInputStream(new FileInputStream(sourceFile)); 
                // 讀取文件,並寫入壓縮流 
                byte[] buffer = new byte[1024]; 
                int readCount = -1; 
                while ((readCount = bin.read(buffer)) != -1) { 
                    bout.write(buffer, 0, readCount); 
                } 
                // 註,在使用緩沖流寫壓縮文件時,一個條件完後一定要刷新,不然可能有的內容就會存入到後面條目中去瞭 
                bout.flush(); 
                // 關閉當前ZIP條目並定位流以寫入下一個條目 
                zos.closeEntry(); 
            } finally { 
                if (bin != null) { 
                    try { bin.close(); } catch (IOException e) {} 
                } 
            } 
        } 
    } 
     
    /**
      * @Description: 
      *     解壓文件
      * @param zipPath 被壓縮文件,請使用絕對路徑
      * @param targetPath 解壓路徑,解壓後的文件將會放入此目錄中,請使用絕對路徑
      *         默認為壓縮文件的路徑的父目錄為解壓路徑
      * @param encoding 解壓編碼
     */ 
    public static void decompress(String zipPath, String targetPath, String encoding) 
            throws FileNotFoundException, ZipException, IOException { 
        // 獲取解縮文件 
        File file = new File(zipPath); 
        if (!file.isFile()) { 
            throw new FileNotFoundException("要解壓的文件不存在"); 
        } 
        // 設置解壓路徑 
        if (targetPath == null || "".equals(targetPath)) { 
            targetPath = file.getParent(); 
        } 
        // 設置解壓編碼 
        if (encoding == null || "".equals(encoding)) { 
            encoding = "GBK"; 
        } 
        // 實例化ZipFile對象 
        ZipFile zipFile = new ZipFile(file, encoding); 
        // 獲取ZipFile中的條目 
        Enumeration<ZipEntry> files = zipFile.getEntries(); 
        // 迭代中的每一個條目 
        ZipEntry entry = null; 
        // 解壓後的文件 
        File outFile = null; 
        // 讀取壓縮文件的輸入流 
        BufferedInputStream bin = null; 
        // 寫入解壓後文件的輸出流 
        BufferedOutputStream bout = null; 
        while (files.hasMoreElements()) { 
            // 獲取解壓條目 
            entry = files.nextElement(); 
            // 實例化解壓後文件對象 
            outFile = new File(targetPath + File.separator + entry.getName()); 
            // 如果條目為目錄,則跳向下一個 
            if (entry.getName().endsWith(File.separator)) { 
                outFile.mkdirs(); 
                continue; 
            } 
            // 創建目錄 
            if (!outFile.getParentFile().exists()) { 
                outFile.getParentFile().mkdirs(); 
            } 
            // 創建新文件 
            outFile.createNewFile(); 
            // 如果不可寫,則跳向下一個條目 
            if (!outFile.canWrite()) { 
                continue; 
            } 
            try { 
                // 獲取讀取條目的輸入流 
                bin = new BufferedInputStream(zipFile.getInputStream(entry)); 
                // 獲取解壓後文件的輸出流 
                bout = new BufferedOutputStream(new FileOutputStream(outFile)); 
                // 讀取條目,並寫入解壓後文件 
                byte[] buffer = new byte[1024]; 
                int readCount = -1; 
                while ((readCount = bin.read(buffer)) != -1) { 
                    bout.write(buffer, 0, readCount); 
                } 
            } finally { 
                try { 
                    bin.close(); 
                    bout.flush(); 
                    bout.close(); 
                } catch (Exception e) {} 
            } 
        } 
    } 
     
    public static void main(String[] args) throws Exception{ 
        //compressTest(); 
        //compressTest2(); 
        //decompressTest(); 
    } 
     
    public static void compressTest() throws Exception { 
        String sourcePath = "E:" + File.separator + "文檔" + File.separator + "音樂"; 
        String zipPath = "E:" + File.separator + "我的音樂.zip"; 
        String comment = "音樂壓縮文件"; 
        compress(sourcePath, zipPath, "GBK", comment); 
    } 
     
    public static void decompressTest() throws Exception { 
        String zipPath = "E:" + File.separator + "我的音樂.zip"; 
        String targetPath = "E:" + File.separator + "temp"; 
        decompress(zipPath, targetPath, "GBK"); 
    } 
     
    public static void compressTest2() throws Exception { 
        List<String> list = new ArrayList<String>(); 
        list.add("E:" + File.separator + "文檔" + File.separator + "音樂"); 
        list.add("E:" + File.separator + "文檔" + File.separator + "視頻"); 
        list.add("E:" + File.separator + "文檔" + File.separator + "資料"); 
        list.add("E:" + File.separator + "文檔" + File.separator + "書籍"); 
        String zipPath = "E:" + File.separator + "我的文檔壓縮文件.zip"; 
        String comment = "我的文檔壓縮文件"; 
        compress(list, zipPath, "GBK", comment); 
    } 
     

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。