ZIP工具类

说明

ZIP常用方法工具类


代码

java 复制代码
import lombok.extern.slf4j.Slf4j;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

@Slf4j
public class ZipUtil {
    private static final String EMPTY_STRING = "";

    /**
     * 把目录下所有文件压缩到zip文件
     *
     * @param compressPath 待压缩目录
     * @param zipFilePath  zip文件
     */
    public static void zip(String compressPath, String zipFilePath) {
        zip(listFiles(compressPath), zipFilePath, compressPath);
    }

    /**
     * 把目录下所有文件压缩到输出流
     *
     * @param compressPath 待压缩目录
     * @param outputStream 输出流
     */
    public static void zip(String compressPath, OutputStream outputStream) {
        zip(listFiles(compressPath), outputStream, compressPath);
    }

    /**
     * 列出目录下所有文件
     *
     * @param path 目录
     * @return 目录下所有文件
     */
    private static List<File> listFiles(String path) {
        File file = new File(path);
        List<File> list = new ArrayList<>();
        if (file.exists()) {
            doListFiles(file, list);
        }
        return list;
    }

    /**
     * 真正执行列出目录下所有文件的方法
     *
     * @param file 目录或文件
     * @param list 目录下所有文件
     */
    private static void doListFiles(File file, List<File> list) {
        if (!file.exists()) {
            return;
        }
        if (file.isFile()) {
            list.add(file);
            return;
        }
        for (File subFile : Objects.requireNonNull(file.listFiles())) {
            if (!subFile.exists()) {
                continue;
            }
            if (subFile.isFile()) {
                list.add(subFile);
            } else {
                doListFiles(subFile, list);
            }
        }
    }

    /**
     * 把目录下所有文件压缩到zip文件
     *
     * @param files       待压缩文件集合
     * @param zipFilePath zip文件
     */
    public static void zip(List<File> files, String zipFilePath) {
        zip(files, zipFilePath, EMPTY_STRING);
    }

    /**
     * 把目录下所有文件压缩到zip文件
     *
     * @param files       待压缩文件集合
     * @param zipFilePath zip文件
     * @param parentPath  待压缩文件最上层目录,用于确定文件的相对路径
     */
    public static void zip(List<File> files, String zipFilePath, String parentPath) {
        try (FileOutputStream fos = new FileOutputStream(zipFilePath)) {
            zip(files, fos, parentPath);
        } catch (IOException exception) {
            log.error(exception.getMessage());
        }
    }

    /**
     * 把目录下所有文件压缩到输出流
     *
     * @param files        待压缩文件集合
     * @param outputStream 输出流
     */
    public static void zip(List<File> files, OutputStream outputStream) {
        zip(files, outputStream, EMPTY_STRING);
    }

    /**
     * 把目录下所有文件压缩到输出流
     *
     * @param files        待压缩文件集合
     * @param outputStream 输出流
     * @param parentPath   待压缩文件最上层目录,用于确定文件的相对路径
     */
    public static void zip(List<File> files, OutputStream outputStream, String parentPath) {
        try (ZipOutputStream zos = new ZipOutputStream(outputStream)) {
            byte[] tmp = new byte[1024];
            Path parent = Paths.get(parentPath).normalize().toAbsolutePath();
            for (File file : files) {
                String relPath = EMPTY_STRING.equals(parentPath) ? file.getName() :
                        parent.relativize(Paths.get(file.getAbsolutePath()).normalize().toAbsolutePath()).toString();
                ZipEntry entry = new ZipEntry(relPath);
                zos.putNextEntry(entry);
                try (FileInputStream fis = new FileInputStream(file)) {
                    int len;
                    while ((len = fis.read(tmp)) > 0) {
                        zos.write(tmp, 0, len);
                    }
                }
                zos.closeEntry();
            }
        } catch (IOException exception) {
            log.error(exception.getMessage());
        }
    }

    /**
     * 解压缩文件
     *
     * @param zipFilePath   压缩文件
     * @param destDirectory 解压缩目录
     * @return 解压缩出来的文件集合
     */
    public static List<String> unzip(String zipFilePath, String destDirectory) {
        File directory = new File(destDirectory);
        if (!directory.exists()) {
            directory.mkdirs();
        }
        List<String> list = new ArrayList<>();
        try (FileInputStream fis = new FileInputStream(zipFilePath);
             ZipInputStream zis = new ZipInputStream(fis)) {
            ZipEntry entry = zis.getNextEntry();
            while (entry != null) {
                String filePath = Paths.get(destDirectory + File.separator + entry.getName())
                        .normalize()
                        .toAbsolutePath()
                        .toString();
                if (entry.isDirectory()) {
                    new File(filePath).mkdirs();
                } else {
                    decompressFile(zis, filePath);
                    list.add(filePath);
                }
                zis.closeEntry();
                entry = zis.getNextEntry();
            }
        } catch (IOException exception) {
            log.error(exception.getMessage());
        }
        return list;
    }

    /**
     * 解压文件
     *
     * @param zis      压缩文件流
     * @param filePath 解压路径
     */
    private static void decompressFile(ZipInputStream zis, String filePath) {
        File file = new File(filePath);
        File parentFile = file.getParentFile();
        if (!parentFile.exists()) {
            parentFile.mkdirs();
        }
        try (FileOutputStream fos = new FileOutputStream(file);
             BufferedOutputStream bos = new BufferedOutputStream(fos)) {
            byte[] tmp = new byte[1024];
            int len;
            while ((len = zis.read(tmp)) > 0) {
                bos.write(tmp, 0, len);
            }
            bos.flush();
        } catch (IOException exception) {
            log.error(exception.getMessage());
        }
    }
}
相关推荐
桦说编程3 小时前
深入解析CompletableFuture源码实现(2)———双源输入
java·后端·源码
lang201509283 小时前
Spring Boot优雅关闭全解析
java·spring boot·后端
pengzhuofan4 小时前
第10章 Maven
java·maven
百锦再5 小时前
Vue Scoped样式混淆问题详解与解决方案
java·前端·javascript·数据库·vue.js·学习·.net
刘一说5 小时前
Spring Boot 启动慢?启动过程深度解析与优化策略
java·spring boot·后端
壹佰大多5 小时前
【spring如何扫描一个路径下被注解修饰的类】
java·后端·spring
百锦再5 小时前
对前后端分离与前后端不分离(通常指服务端渲染)的架构进行全方位的对比分析
java·开发语言·python·架构·eclipse·php·maven
DokiDoki之父5 小时前
Spring—注解开发
java·后端·spring
CodeCraft Studio6 小时前
【能源与流程工业案例】KBC借助TeeChart 打造工业级数据可视化平台
java·信息可视化·.net·能源·teechart·工业可视化·工业图表