1. 程式人生 > >java實現壓縮、解壓

java實現壓縮、解壓

package com.chen.stu.io;
 
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
 
/**
 * Zip壓縮/解壓縮工具類
 * 實現對目標路徑及其子路徑下的所有檔案及空目錄的壓縮
 * 參考網上若干種實現,並修改其bug
 *
 */
public class ZipUtil {
 
    /** 緩衝器大小 */
    private static final int BUFFER = 512;
 
    /**
     * 取的給定源目錄下的所有檔案及空的子目錄
     * 遞迴實現
     *
     * @param srcFile
     *
     * @return
     */
    private static List<File> getAllFiles(File srcFile) {
        List<File> fileList = new ArrayList<File>();
        File[]     tmp      = srcFile.listFiles();
 
        for (int i = 0; i < tmp.length; i++) {
 
            if (tmp[i].isFile()) {
                fileList.add(tmp[i]);
                System.out.println("add file: "+tmp[i].getName());
            }
 
            if (tmp[i].isDirectory()) {
                if (tmp[i].listFiles().length!=0){//若不是空目錄,則遞迴新增其下的目錄和檔案
                    fileList.addAll(getAllFiles(tmp[i]));
                }
                else{//若是空目錄,則新增這個目錄到fileList
                    fileList.add(tmp[i]);
                    System.out.println("add empty dir: "+tmp[i].getName());
                }
            }
        }    // end for
 
        return fileList;
    }
 
    /**
     * 取相對路徑
     * 依據檔名和壓縮源路徑得到檔案在壓縮源路徑下的相對路徑
     *
     * @param dirPath 壓縮源路徑
     * @param file
     *
     * @return 相對路徑
     */
    private static String getRelativePath(String dirPath, File file) {
        File   dir          = new File(dirPath);
        String relativePath = file.getName();
 
        while (true) {
            file = file.getParentFile();
 
            if (file == null) {
                break;
            }
 
            if (file.equals(dir)) {
                break;
            } else {
                relativePath = file.getName() + "/" + relativePath;
            }
        }    // end while
 
        return relativePath;
    }
 
    /**
     * 建立檔案
     * 根據壓縮包內檔名和解壓縮目的路徑,建立解壓縮目標檔案,
     * 生成中間目錄
     * @param dstPath 解壓縮目的路徑
     * @param fileName 壓縮包內檔名
     *
     * @return 解壓縮目標檔案
     *
     * @throws IOException
     */
    private static File createFile(String dstPath, String fileName) throws IOException {
        String[] dirs = fileName.split("/");//將檔名的各級目錄分解
        File     file = new File(dstPath);
 
        if (dirs.length > 1) {//檔案有上級目錄
            for (int i = 0; i < dirs.length - 1; i++) {
                file = new File(file, dirs[i]);//依次建立檔案物件知道檔案的上一級目錄
            }
 
            if (!file.exists()) {
                file.mkdirs();//檔案對應目錄若不存在,則建立
                System.out.println("mkdirs: " + file.getCanonicalPath());
            }
 
            file = new File(file, dirs[dirs.length - 1]);//建立檔案
 
            return file;
        } else {
            if (!file.exists()) {
                file.mkdirs();//若目標路徑的目錄不存在,則建立
                System.out.println("mkdirs: " + file.getCanonicalPath());
            }
 
            file = new File(file, dirs[0]);//建立檔案
 
            return file;
        }
    }
 
    /**
     * 解壓縮方法
     *
     *
     * @param zipFileName 壓縮檔名
     * @param dstPath 解壓目標路徑
     *
     * @return
     */
    public static boolean unzip(String zipFileName, String dstPath) {
        System.out.println("zip uncompressing...");
 
        try {
            @SuppressWarnings("resource")
			ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(zipFileName));
            ZipEntry       zipEntry       = null;
            byte[]         buffer         = new byte[BUFFER];//緩衝器
            int            readLength     = 0;//每次讀出來的長度
 
            while ((zipEntry = zipInputStream.getNextEntry()) != null) {
                if (zipEntry.isDirectory()) {//若是zip條目目錄,則需建立這個目錄
                    File dir = new File(dstPath + "/" + zipEntry.getName());
 
                    if (!dir.exists()) {
                        dir.mkdirs();
                        System.out.println("mkdirs: " + dir.getCanonicalPath());
 
                        continue;//跳出
                    }
                }
 
                File file = createFile(dstPath, zipEntry.getName());//若是檔案,則需建立該檔案
 
                System.out.println("file created: " + file.getCanonicalPath());
 
                OutputStream outputStream = new FileOutputStream(file);
 
                while ((readLength = zipInputStream.read(buffer, 0, BUFFER)) != -1) {
                    outputStream.write(buffer, 0, readLength);
                }
 
                outputStream.close();
                System.out.println("file uncompressed: " + file.getCanonicalPath());
            }    // end while
        } catch (FileNotFoundException e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
            System.out.println("unzip fail!");
 
            return false;
        } catch (IOException e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
            System.out.println("unzip fail!");
 
            return false;
        }
 
        System.out.println("unzip success!");
 
        return true;
    }
 
    /**
     * 壓縮方法
     * (可以壓縮空的子目錄)
     * @param srcPath 壓縮源路徑
     * @param zipFileName 目標壓縮檔案
     *
     * @return
     */
    public static boolean zip(String srcPath, String zipFileName) {
        System.out.println("zip compressing...");
 
        File       srcFile    = new File(srcPath);
        List<File> fileList   = getAllFiles(srcFile);//所有要壓縮的檔案
        byte[]     buffer     = new byte[BUFFER];//緩衝器
        ZipEntry   zipEntry   = null;
        int        readLength = 0;//每次讀出來的長度
 
        try {
            ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(zipFileName));
 
            for (File file : fileList) {
                if (file.isFile()){//若是檔案,則壓縮這個檔案
                    zipEntry = new ZipEntry(getRelativePath(srcPath, file));
                    zipEntry.setSize(file.length());
                    zipEntry.setTime(file.lastModified());
                    zipOutputStream.putNextEntry(zipEntry);
 
                    InputStream inputStream = new BufferedInputStream(new FileInputStream(file));
 
                    while ((readLength = inputStream.read(buffer, 0, BUFFER)) != -1) {
                        zipOutputStream.write(buffer, 0, readLength);
                    }
 
                    inputStream.close();
                    System.out.println("file compressed: " + file.getCanonicalPath());
                }else {//若是目錄(即空目錄)則將這個目錄寫入zip條目
                    zipEntry = new ZipEntry(getRelativePath(srcPath, file)+"/");
                    zipOutputStream.putNextEntry(zipEntry);
                    System.out.println("dir compressed: " + file.getCanonicalPath()+"/");
                }
 
            }    // end for
 
            zipOutputStream.close();
        } catch (FileNotFoundException e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
            System.out.println("zip fail!");
 
            return false;
        } catch (IOException e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
            System.out.println("zip fail!");
 
            return false;
        }
 
        System.out.println("zip success!");
 
        return true;
    }
    
    public static void main(String[] args) {
    	zip("C:\\Users\\jj\\Desktop\\區政府原型_安全巡查20181008", "D:\\TE.zip");
	}
}
 
 
//~ Formatted by Jindent --- http://www.jindent.com