Java實現多層目錄打包和解壓--解決了壓縮不了空文件夾的問題

依賴:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-compress -->
<!-- 處理壓縮解壓 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-compress</artifactId>
    <version>1.9</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-io -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-io</artifactId>
    <version>1.3.2</version>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.4</version>
</dependency>

工具類: 

package com.fsc.zip_utils.utils;


import org.apache.commons.lang3.StringUtils;

import java.io.*;
import java.util.zip.*;

public class ZipUtil {

    private static final String TAG = "ZipUtil";

    /**
     * 解壓文件到指定文件夾
     *
     * @param zip      源文件
     * @param destPath 目標文件夾路徑
     * @throws Exception 解壓失敗
     */
    public static void decompress(String zip, String destPath) throws Exception {
        //參數檢查
        if (StringUtils.isEmpty(zip) || StringUtils.isEmpty(destPath)) {
            throw new IllegalArgumentException("zip or destPath is illegal");
        }
        File zipFile = new File(zip);
        if (!zipFile.exists()) {
            throw new FileNotFoundException("zip file is not exists");
        }
        File destFolder = new File(destPath);
        if (!destFolder.exists()) {
            if (!destFolder.mkdirs()) {
                throw new FileNotFoundException("destPath mkdirs is failed");
            }
        }
        ZipInputStream zis = null;
        BufferedOutputStream bos = null;
        try {
            zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(zip)));
            ZipEntry ze;
            while ((ze = zis.getNextEntry()) != null) {
                //得到解壓文件在當前存儲的絕對路徑
                String filePath = destPath + File.separator + ze.getName();
                if (ze.isDirectory()) {
                    new File(filePath).mkdirs();
                } else {
                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    byte[] buffer = new byte[1024];
                    int count;
                    while ((count = zis.read(buffer)) != -1) {
                        baos.write(buffer, 0, count);
                    }
                    byte[] bytes = baos.toByteArray();
                    File entryFile = new File(filePath);
                    //創建父目錄
                    if (!entryFile.getParentFile().exists()) {
                        if (!entryFile.getParentFile().mkdirs()) {
                            throw new FileNotFoundException("zip entry mkdirs is failed");
                        }
                    }
                    //寫文件
                    bos = new BufferedOutputStream(new FileOutputStream(entryFile));
                    bos.write(bytes);
                    bos.flush();
                }

            }
        } finally {
            closeQuietly(zis);
            closeQuietly(bos);
        }
    }

    /**
     * @param srcPath  源文件的絕對路徑,可以爲文件或文件夾
     * @param destPath 目標文件的絕對路徑  /sdcard/.../file_name.zip
     * @throws Exception 解壓失敗
     */
    public static void compress(String srcPath, String destPath) throws Exception {
        //參數檢查
        if (StringUtils.isEmpty(srcPath) || StringUtils.isEmpty(destPath)) {
            throw new IllegalArgumentException("srcPath or destPath is illegal");
        }
        File srcFile = new File(srcPath);
        if (!srcFile.exists()) {
            throw new FileNotFoundException("srcPath file is not exists");
        }
        File destFile = new File(destPath);
        if (destFile.exists()) {
            if (!destFile.delete()) {
                throw new IllegalArgumentException("destFile is exist and do not delete.");
            }
        }

        CheckedOutputStream cos = null;
        ZipOutputStream zos = null;
        try {
            // 對目標文件做CRC32校驗,確保壓縮後的zip包含CRC32值
            cos = new CheckedOutputStream(new FileOutputStream(destPath), new CRC32());
            //裝飾一層ZipOutputStream,使用zos寫入的數據就會被壓縮啦
            zos = new ZipOutputStream(cos);
            zos.setLevel(9);//設置壓縮級別 0-9,0表示不壓縮,1表示壓縮速度最快,9表示壓縮後文件最小;默認爲6,速率和空間上得到平衡。
            if (srcFile.isFile()) {
                compressFile("", srcFile, zos);
            } else if (srcFile.isDirectory()) {
                compressFolder("", srcFile, zos);
            }
        } finally {
            closeQuietly(zos);
        }
    }

    private static void compressFolder(String prefix, File srcFolder, ZipOutputStream zos) throws IOException {
        String new_prefix = prefix + srcFolder.getName() + "/";
        File[] files = srcFolder.listFiles();
        //支持空文件夾
        if (files.length == 0) {
            compressFile(prefix, srcFolder, zos);
        } else {
            for (File file : files) {
                if (file.isFile()) {
                    compressFile(new_prefix, file, zos);
                } else if (file.isDirectory()) {
                    compressFolder(new_prefix, file, zos);
                }
            }
        }
    }

    /**
     * 壓縮文件和空目錄
     *
     * @param prefix
     * @param src
     * @param zos
     * @throws IOException
     */
    private static void compressFile(String prefix, File src, ZipOutputStream zos) throws IOException {
        //若是文件,那肯定是對單個文件壓縮
        //ZipOutputStream在寫入流之前,需要設置一個zipEntry
        //注意這裏傳入參數爲文件在zip壓縮包中的路徑,所以只需要傳入文件名即可
        String relativePath = prefix + src.getName();
        if (src.isDirectory()) {
            relativePath += "/";
        }
        ZipEntry entry = new ZipEntry(relativePath);
        //寫到這個zipEntry中,可以理解爲一個壓縮文件
        zos.putNextEntry(entry);
        InputStream is = null;
        try {
            if (src.isFile()) {
                is = new FileInputStream(src);
                byte[] buffer = new byte[1024 << 3];
                int len = 0;
                while ((len = is.read(buffer)) != -1) {
                    zos.write(buffer, 0, len);
                }
            }
            //該文件寫入結束
            zos.closeEntry();
        } finally {
            closeQuietly(is);
        }
    }

    private static void closeQuietly(final Closeable closeable) {
        try {
            if (closeable != null) {
                closeable.close();
            }
        } catch (final IOException ioe) {
            // ignore
        }
    }

    /**
     * Json字符串進行打包
     *
     * @param tempFilePath 臨時文件存放的地方(以正斜線結尾) F:/
     * @param filename     文件名,fusc.txt
     * @param destPath     目標文件的絕對路徑  F:/ziped/dudududududdududu.zip
     * @param jsonStr      文件內的json字符串
     * @throws Exception
     */
    public static void compressJsonStr(String tempFilePath, String filename, String destPath, String jsonStr) throws Exception {
        File tempFile = new File(tempFilePath);
        if (!tempFile.exists()) {
            tempFile.mkdir();
        }
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(tempFilePath + filename));
        bufferedWriter.write(jsonStr);
        bufferedWriter.close();
        ZipUtil.compress(tempFilePath + filename, destPath);
        File file = new File(tempFilePath + filename);
        file.delete();
        if (tempFile.listFiles().length <= 0) {
            tempFile.delete();
        }
    }

}

源碼下載地址(springboot項目,導入idea即可使用):

https://pan.baidu.com/s/1JE1vAeFPogDOEGFd1VLrtw

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章