记录一下递归解压压缩包的实现方法

这个方法可以直接使用

package com.shenyh.estimate.util;

import com.shenyh.exception.ServiceException;
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.apache.commons.compress.archivers.zip.ZipFile;
import org.apache.commons.compress.utils.IOUtils;

import java.io.*;
import java.util.Enumeration;
import java.util.Objects;

public class FileRecursionUtil {

    /**
     * 递归解压zip文件
     *
     * @param zip        zip文件路径
     * @param targetPath 解压后存放的文件路径
     * @return void
     */
    public File unZipRecursion(File zip, String targetPath) {
        unZip(zip, targetPath);
        scanFilesWithRecursion(targetPath);
        return new File(targetPath);
    }

    /**
     * 解压zip文件
     *
     * @param srcFile     zip文件路径
     * @param destDirPath 解压后存放的文件路径
     * @return boolean
     */
    public boolean unZip(File srcFile, String destDirPath) {

        //校验zip包格式
        zipIsRight(srcFile);

        // 开始解压
        try (ZipFile zipFile = new ZipFile(srcFile)) {
            Enumeration<ZipArchiveEntry> entries = zipFile.getEntries();
            while (entries.hasMoreElements()) {
                ZipArchiveEntry entry = entries.nextElement();
                // 如果是文件夹,就创建个文件夹
                if (entry.isDirectory()) {
                    String dirPath = destDirPath + File.separator + entry.getName();
                    File dir = new File(dirPath);
                    dir.mkdirs();
                } else {
                    // 如果是文件,就先创建一个文件,然后用io流把内容copy过去
                    File targetFile = new File(destDirPath + File.separator + entry.getName());
                    // 保证这个文件的父文件夹必须要存在
                    if (!targetFile.getParentFile().exists()) {
                        targetFile.getParentFile().mkdirs();
                    }
                    boolean newFile = targetFile.createNewFile();
                    if (newFile) {
                        // 将压缩文件内容写入到这个文件中
                        try (InputStream is = zipFile.getInputStream(entry); FileOutputStream fos = new FileOutputStream(targetFile)) {
                            int len;
                            byte[] buf = new byte[2048];
                            while ((len = is.read(buf)) != -1) {
                                fos.write(buf, 0, len);
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 遍历文件夹,有压缩文件就进行解压
     *
     * @param folderPath 需要解压的文件夹路径
     * @return void
     */
    public void scanFilesWithRecursion(String folderPath) {
        File directory = new File(folderPath);
        // 遍历文件夹
        if (directory.isDirectory()) {
            File[] fileList = directory.listFiles();
            for (int i = 0; i < Objects.requireNonNull(fileList).length; i++) {
                String name = fileList[i].getAbsolutePath().substring(fileList[i].getAbsolutePath().lastIndexOf(".") + 1);
                // 如果是zip文件,解密
                if ("zip".equals(name)) {
                    boolean flag = unZip(new File(fileList[i].getAbsolutePath()), fileList[i].getParent());
                    if (flag) {
                        // 解压成功,删除压缩包
                        fileList[i].delete();
                    }
                    // 递归
                    scanFilesWithRecursion(fileList[i].getParent());
                } else if (new File(fileList[i].getPath()).isDirectory()) {
                    // 递归
                    scanFilesWithRecursion(fileList[i].getPath());
                }
            }
        }
    }


    /**
     * 判断zip文件是否为正确的zip文件
     *
     * @param file
     */
    public static void zipIsRight(File file) {
        try (ZipFile zipFile = new ZipFile(file)) {
            // 如果zip文件没有密码,那么可以正常打开,不会抛出异常
            // 判断压缩包内容是否为空
            if (zipIsNull(file)) {
                throw new ServiceException("压缩包的内容为空!");
            }
            Enumeration<ZipArchiveEntry> entries = zipFile.getEntries();
            while (entries.hasMoreElements()) {
                ZipArchiveEntry entry = entries.nextElement();
                int method = entry.getMethod();
                if (!isCommonCompressionMethod(method)) {
                    throw new ServiceException("请检查压缩包压缩方式是否为以下几种:标准压缩、BZIP2、LZMA、PPMD!");
                }
            }
        } catch (IOException e) {
            // 如果zip文件有密码,那么打开时会抛出IOException
            throw new ServiceException("请不要上传带有密码的压缩包或者非法压缩包");
        }
    }

    /**
     * 判断zip内容是否为空
     */
    public static boolean zipIsNull(File file) {
        FileInputStream fis = null;
        boolean flag = true;
        try {
            fis = new FileInputStream(file);
            ZipArchiveInputStream zis = new ZipArchiveInputStream(fis);
            ArchiveEntry entry;
            while ((entry = zis.getNextEntry()) != null) {
                if (!entry.isDirectory()) {
                    flag = false;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(fis);
        }
        return flag;
    }


    /**
     * 判断是否为常见的压缩方式
     */
    private static boolean isCommonCompressionMethod(int method) {
        return method == ZipArchiveEntry.STORED ||  // 0
                method == ZipArchiveEntry.DEFLATED ||  // 8
                method == 12 ||  // BZIP2
                method == 14 ||  // LZMA
                method == 98 || // PPMD
                method == 9  //DEFLATED64
                ;
    }
}

  

posted @ 2025-02-25 14:31  热心网友小沈  阅读(61)  评论(0)    收藏  举报