1. 程式人生 > >Java解壓縮zip檔案工具類(支援zip資料夾下多級目錄結構)

Java解壓縮zip檔案工具類(支援zip資料夾下多級目錄結構)

文章目錄


Java解壓縮zip檔案工具類(支援zip資料夾下多級目錄結構)

1. 前言

由於工作需要一個能夠解壓縮zip的工具類,但查看了不少部落格,發現檢視的文章裡都只支援zip資料夾下的一級檔案結構,但實際生活中,zip資料夾下存在多級目錄及檔案是很隨意的事情,所以萌生了封裝這樣一個能夠解壓縮多級目錄結構檔案的想法。

2. 正文

2.1 解壓縮後文件目錄結構展示

在這裡插入圖片描述

2.2 注意事項

  • 若zip檔案中包含中文的話,可能需要制定字元編碼,若不指定的話,預設使用UTF8字元編碼
  • Windows系統壓縮編碼一般為GBKGB2312UTF8Linux系統壓縮編碼一般為UTF8
  • 測試資料使用GB2312能夠正常解碼,使用其它均不能正常解碼

2.3 異常

2.3.1 可能會遇到的異常
java.lang.IllegalArgumentException: MALFORMED
	at java.util.zip.ZipCoder.toString(ZipCoder.
java:58) at java.util.zip.ZipFile.getZipEntry(ZipFile.java:583) at java.util.zip.ZipFile.access$900(ZipFile.java:60) at java.util.zip.ZipFile$ZipEntryIterator.next(ZipFile.java:539) at java.util.zip.ZipFile$ZipEntryIterator.nextElement(ZipFile.java:514) at java.util.zip.ZipFile$ZipEntryIterator.nextElement
(ZipFile.java:495) at com.tdt.sc.utils.FileUtils.unpack(FileUtils.java:91) at com.tdt.sc.utils.FileUtils.unpack(FileUtils.java:54) at com.tdt.sc.utils.FileUtils.unpack(FileUtils.java:34) at com.tdt.sc.utils.FileUtils.main(FileUtils.java:23)
2.3.2 解決方案
  • 此異常為字元編碼解碼異常
  • 建議使用其它字元編碼進行解碼,具體參見 注意事項

2.4 具體程式碼實現

import java.io.*;
import java.nio.charset.Charset;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/**
 * @program: 
 * @description: 檔案解壓縮工具類
 * @author: Mr.superbeyone
 * @create: 2018-10-23 14:04
 **/
public class FileUtils {

    /**
     *  此方法將預設設定解壓縮後文件的儲存路徑為zip檔案所在路徑
     *      即解壓縮到當前資料夾下
     * @param zip zip檔案位置
     * @param charsetName 字元編碼
     */
    public static void unpack(String zip, String charsetName) {
        unpack(new File(zip), charsetName);
    }

    /**
     *
     * @param zip zip檔案位置
     * @param outputDir 解壓縮後文件儲存路徑
     * @param charsetName 字元編碼
     */
    public static void unpack(String zip, String outputDir, String charsetName) {
        unpack(new File(zip), new File(outputDir), charsetName);
    }

    /**
     *  此方法將預設設定解壓縮後文件的儲存路徑為zip檔案所在路徑
     *      即解壓縮到當前資料夾
     * @param zip zip檔案位置
     * @param charsetName 字元編碼
     */
    public static void unpack(File zip, String charsetName) {
        unpack(zip, null, charsetName);
    }

    /**
     *
     * @param zip zip檔案位置
     * @param outputDir 解壓縮後文件儲存路徑
     */
    public static void unpack(File zip, File outputDir) {
        unpack(zip, outputDir, "");
    }

    /**
     *
     * @param zip zip檔案位置
     * @param outputDir 解壓縮後文件儲存路徑
     * @param charsetName 字元編碼
     */
    public static void unpack(File zip, File outputDir, String charsetName) {

        FileOutputStream out = null;
        InputStream in = null;
        //讀出檔案資料
        ZipFile zipFileData = null;
        ZipFile zipFile = null;
        try {
            //若目標儲存檔案位置不存在
            if (outputDir != null) if (!outputDir.exists()) {
                outputDir.mkdirs();
            }
            if (charsetName != null && charsetName != "") {
                zipFile = new ZipFile(zip.getPath(), Charset.forName(charsetName));
            } else {
                zipFile = new ZipFile(zip.getPath(), Charset.forName("utf8"));
            }
            //zipFile = new ZipFile(zip.getPath(), Charset.forName(charsetName));
            Enumeration<? extends ZipEntry> entries = zipFile.entries();
            //處理建立資料夾
            while (entries.hasMoreElements()) {
                ZipEntry entry = entries.nextElement();
                String filePath = "";

                if (outputDir == null) {
                    filePath = zip.getParentFile().getPath() + File.separator + entry.getName();
                } else {
                    filePath = outputDir.getPath() + File.separator + entry.getName();
                }
                File file = new File(filePath);
                File parentFile = file.getParentFile();
                if (!parentFile.exists()) {
                    parentFile.mkdirs();
                }
                if (parentFile.isDirectory()) {
                    continue;
                }
            }
            if (charsetName != null && charsetName != "") {
                zipFileData = new ZipFile(zip.getPath(), Charset.forName(charsetName));
            } else {
                zipFileData = new ZipFile(zip.getPath(), Charset.forName("utf8"));
            }
            Enumeration<? extends ZipEntry> entriesData = zipFileData.entries();
            while (entriesData.hasMoreElements()) {
                ZipEntry entry = entriesData.nextElement();
                in = zipFile.getInputStream(entry);
                String filePath = "";
                if (outputDir == null) {
                    filePath = zip.getParentFile().getPath() + File.separator + entry.getName();
                } else {
                    filePath = outputDir.getPath() + File.separator + entry.getName();
                }
                File file = new File(filePath);
                if (file.isDirectory()) {
                    continue;
                }
                out = new FileOutputStream(filePath);
                int len = -1;
                byte[] bytes = new byte[1024];
                while ((len = in.read(bytes)) != -1) {
                    out.write(bytes, 0, len);
                }
                out.flush();
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                out.close();
                in.close();
                zipFile.close();
                zipFileData.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

2.4 遺留問題

以下問題未做處理:

  1. 壓縮檔案內可能包含其它壓縮檔案
  2. 壓縮檔案內若存在空資料夾,則該資料夾會被當成檔案處理,即生成以該資料夾名命名的空檔案