用Java实现在Windows/Linux环境,压缩文件和解压文件 zip格式

package com.gec.it.excel.write;
import java.io.*;
import java.nio.charset.Charset;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.Properties;
import java.util.stream.Collectors;
import java.util.zip.*;

/**
 * @Author Miracle xyt
 * @Date 2024/7/10 17:12
 * @Version 1.0
 */

public class ZipUtils {

    /**
     * 解压文件
     *
     * @param file      压缩文件
     * @param targetDir 解压文件输出的目录
     * @throws IOException
     */
    public static void unPacket(Path file, Path targetDir) throws IOException {
        if (!Files.exists(targetDir)) {
            Files.createDirectories(targetDir);
        }
        // 创建zip对象
        ZipFile zipFile = new ZipFile(file.toFile());
        try {
            // 读取zip流
            try (ZipInputStream zipInputStream = new ZipInputStream(Files.newInputStream(file), Charset.forName("GBK"))) {
                ZipEntry zipEntry = null;
                // 遍历每一个zip项
                while ((zipEntry = zipInputStream.getNextEntry()) != null) {
                    // 获取zip项目名称
                    String entryName = zipEntry.getName();
                    // 构建绝对路径
                    Path entryFile = targetDir.resolve(entryName);
                    if (zipEntry.isDirectory()) {    // 文件夹
                        if (!Files.isDirectory(entryFile)) {
                            Files.createDirectories(entryFile);
                        }
                    } else {                            // 文件
                        // 读取zip项数据流
                        try (InputStream zipEntryInputStream = zipFile.getInputStream(zipEntry)) {
                            try (OutputStream fileOutputStream = Files.newOutputStream(entryFile, StandardOpenOption.CREATE_NEW)) {
                                byte[] buffer = new byte[4096];
                                int length = 0;
                                while ((length = zipEntryInputStream.read(buffer)) != -1) {
                                    fileOutputStream.write(buffer, 0, length);
                                }
                                fileOutputStream.flush();
                            }
                        }
                    }
                }
            }
        } finally {
            zipFile.close();
        }
    }

    /**
     * 压缩指定的文件
     *
     * @param files   目标文件
     * @param zipFile 生成的压缩文件
     * @throws IOException
     */
    public static void packet(Path[] files, Path zipFile) throws IOException {
        OutputStream outputStream = Files.newOutputStream(zipFile, StandardOpenOption.CREATE);
        ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream);
        try {
            for (Path file : files) {
                if (Files.isDirectory(file)) {
                    continue;
                }
                try (InputStream inputStream = Files.newInputStream(file)) {
                    // 创建一个压缩项,指定名称
                    ZipEntry zipEntry = new ZipEntry(file.getFileName().toString());
                    // 添加到压缩流
                    zipOutputStream.putNextEntry(zipEntry);
                    // 写入数据
                    int len = 0;
                    byte[] buffer = new byte[1024 * 10];
                    while ((len = inputStream.read(buffer)) > 0) {
                        zipOutputStream.write(buffer, 0, len);
                    }
                    zipOutputStream.flush();
                }
            }
            // 完成所有压缩项的添加
            zipOutputStream.closeEntry();
        } finally {
            zipOutputStream.close();
            outputStream.close();
        }
    }

    /**
     * 压缩指定的目录
     *
     * @param folder
     * @param zipFile
     * @throws IOException
     */
    public static void packet(Path folder, Path zipFile) throws IOException {
        if (!Files.isDirectory(folder)) {
            throw new IllegalArgumentException(folder.toString() + " 不是合法的文件夹");
        }

        OutputStream outputStream = Files.newOutputStream(zipFile, StandardOpenOption.CREATE);
        ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream);

        LinkedList<String> path = new LinkedList<>();

        try {
            Files.walkFileTree(folder, new FileVisitor<Path>() {

                @Override
                public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {

                    if (Files.isDirectory(folder)) {
                        // 开始遍历目录
                        String folder = dir.getFileName().toString();
                        path.addLast(folder);
                        // 写入目录
                        ZipEntry zipEntry = new ZipEntry(path.stream().collect(Collectors.joining("/", "", "/")));
                        try {
                            zipOutputStream.putNextEntry(zipEntry);
                            zipOutputStream.flush();
                        } catch (IOException e) {
                            throw new RuntimeException(e);
                        }
                    }
                    return FileVisitResult.CONTINUE;
                }

                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                    // 开始遍历文件
                    try (InputStream inputStream = Files.newInputStream(file)) {

                        // 创建一个压缩项,指定名称
                        String fileName = path.size() > 0
                                ? path.stream().collect(Collectors.joining("/", "", "")) + "/" + file.getFileName().toString()
                                : file.getFileName().toString();

                        ZipEntry zipEntry = new ZipEntry(fileName);

                        // 添加到压缩流
                        zipOutputStream.putNextEntry(zipEntry);
                        // 写入数据
                        int len = 0;
                        byte[] buffer = new byte[1024 * 10];
                        while ((len = inputStream.read(buffer)) > 0) {
                            zipOutputStream.write(buffer, 0, len);
                        }

                        zipOutputStream.flush();
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                    return FileVisitResult.CONTINUE;
                }

                @Override
                public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
                    return FileVisitResult.CONTINUE;
                }

                @Override
                public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
                    // 结束遍历目录
                    if (!path.isEmpty()) {
                        path.removeLast();
                    }
                    return FileVisitResult.CONTINUE;
                }
            });
            zipOutputStream.closeEntry();
        } finally {
            zipOutputStream.close();
            outputStream.close();
        }
    }

    public static boolean isEmpty(String str) {
        return (str == null || "".equals(str));
    }

    /**
     * 递归压缩文件夹
     *
     * @param srcRootDir 压缩文件夹根目录的子路径
     * @param file       当前递归压缩的文件或目录对象
     * @param zos        压缩文件存储对象
     * @throws Exception
     */
    private static void zip(String srcRootDir, File file, ZipOutputStream zos) throws Exception {
        if (file == null) {
            return;
        }

        //如果是文件,则直接压缩该文件
        if (file.isFile()) {
            int count, bufferLen = 1024;
            byte[] data = new byte[bufferLen];

            //获取文件相对于压缩文件夹根目录的子路径
            String subPath = file.getAbsolutePath();
            int index = subPath.indexOf(srcRootDir);
            if (index != -1) {
                subPath = subPath.substring(srcRootDir.length() + File.separator.length());
            }
            ZipEntry entry = new ZipEntry(subPath);
            zos.putNextEntry(entry);
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
            while ((count = bis.read(data, 0, bufferLen)) != -1) {
                zos.write(data, 0, count);
            }
            bis.close();
            zos.closeEntry();
        }
        //如果是目录,则压缩整个目录
        else {
            //压缩目录中的文件或子目录
            File[] childFileList = file.listFiles();
            for (int n = 0; n < childFileList.length; n++) {
                childFileList[n].getAbsolutePath().indexOf(file.getAbsolutePath());
                zip(srcRootDir, childFileList[n], zos);
            }
        }
    }

    /**
     * 对文件或文件目录进行压缩
     *
     * @param srcPath     要压缩的源文件路径。如果压缩一个文件,则为该文件的全路径;如果压缩一个目录,则为该目录的顶层目录路径
     * @param zipPath     压缩文件保存的路径。注意:zipPath不能是srcPath路径下的子文件夹
     * @param zipFileName 压缩文件名
     * @throws Exception
     */
    public static void zip(String srcPath, String zipPath, String zipFileName) throws Exception {

        CheckedOutputStream cos = null;
        ZipOutputStream zos = null;
        try {
            File srcFile = new File(srcPath);

            //判断压缩文件保存的路径是否为源文件路径的子文件夹,如果是,则抛出异常(防止无限递归压缩的发生)
            if (srcFile.isDirectory() && zipPath.indexOf(srcPath) != -1) {
                return;
            }

            //判断压缩文件保存的路径是否存在,如果不存在,则创建目录
            File zipDir = new File(zipPath);
            if (!zipDir.exists() || !zipDir.isDirectory()) {
                zipDir.mkdirs();
            }

            //创建压缩文件保存的文件对象
            String zipFilePath = zipPath + File.separator + zipFileName;
            File zipFile = new File(zipFilePath);
            if (zipFile.exists()) {
                //检测文件是否允许删除,如果不允许删除,将会抛出SecurityException
                SecurityManager securityManager = new SecurityManager();
                securityManager.checkDelete(zipFilePath);
                //删除已存在的目标文件
                zipFile.delete();
            }

            cos = new CheckedOutputStream(new FileOutputStream(zipFile), new CRC32());
            zos = new ZipOutputStream(cos);

            //如果只是压缩一个文件,则需要截取该文件的父目录
            String srcRootDir = srcPath;
            if (srcFile.isFile()) {
                int index = srcPath.lastIndexOf(File.separator);
                if (index != -1) {
                    srcRootDir = srcPath.substring(0, index);
                }
            }
            //调用递归压缩方法进行目录或文件压缩
            zip(srcRootDir, srcFile, zos);
            zos.flush();
        } catch (Exception e) {
            throw e;
        } finally {
            try {
                if (zos != null) {
                    zos.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 解压缩zip包
     *
     * @param zipFilePath        zip文件的全路径
     * @param unzipFilePath      解压后的文件保存的路径
     * @param includeZipFileName 解压后的文件保存的路径是否包含压缩文件的文件名。true-包含;false-不包含
     */
    public static boolean unZip(String zipFilePath, String unzipFilePath, boolean includeZipFileName) {

        initOS();
        if (isEmpty(zipFilePath) || isEmpty(unzipFilePath)) {
            return false;
        }

        File zipFile = new File(zipFilePath);
        //如果解压后的文件保存路径包含压缩文件的文件名,则追加该文件名到解压路径
        if (includeZipFileName) {
            String fileName = zipFile.getName();
            if (!isEmpty(fileName)) {
                fileName = fileName.substring(0, fileName.lastIndexOf("."));
            }
            unzipFilePath = unzipFilePath + dir_p + fileName;
        }

        //创建解压缩文件保存的路径
        File unzipFileDir = new File(unzipFilePath);
        if ((!unzipFileDir.exists() || !unzipFileDir.isDirectory()) && !unzipFileDir.mkdirs()) {
            return false;
        }

        //开始解压
        ZipEntry entry;
        String entryFilePath;
        String entryDirPath;
        File entryFile;
        File entryDir;
        int index = 0;
        int count = 0;
        int bufferSize = 1024;
        byte[] buffer = new byte[bufferSize];
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;

        ZipFile zip;
        try {
            zip = new ZipFile(zipFile, ZipFile.OPEN_READ, Charset.forName("GBK"));
        } catch (IOException e) {
            return false;
        }

        Enumeration<ZipEntry> entries = (Enumeration<ZipEntry>) zip.entries();
        //循环对压缩包里的每一个文件进行解压
        while (entries.hasMoreElements()) {
            entry = entries.nextElement();
            //构建压缩包中一个文件解压后保存的文件全路径

            String entryName = entry.getName();

            entryFilePath = unzipFilePath + dir_p + entryName;
            //构建解压后保存的文件夹路径
            if (entryName.contains("\\") || entryName.contains("/")) {
                int index1 = entryFilePath.substring(0, entryFilePath.length() - 2).lastIndexOf("\\");
                int index2 = entryFilePath.substring(0, entryFilePath.length() - 2).lastIndexOf("/");
                if (index1 < index2) {
                    index = index2;
                } else {
                    index = index1;
                }

            } else {
                int index1 = entryFilePath.lastIndexOf("\\");
                int index2 = entryFilePath.lastIndexOf("/");
                if (index1 < index2) {
                    index = index2;
                } else {
                    index = index1;
                }

            }

            //获得解压文件上层目录
            if (index != -1) {
                entryDirPath = entryFilePath.substring(0, index);
            } else {
                entryDirPath = "";
            }

            // 创建解压文件上层目录
            entryDir = new File(entryDirPath);
            if ((!entryDir.exists() || !entryDir.isDirectory()) && !entryDir.mkdirs()) {
                return false;
            }

            //创建解压文件
            entryFile = new File(entryFilePath);
            if (entryFile.exists() && entryFile.isFile()) {
                //删除已存在的目标文件
                if (!entryFile.delete()) {
                }
            }

            if (!entry.isDirectory()) {
                //写入文件
                try {
                    bos = new BufferedOutputStream(new FileOutputStream(entryFile));
                    bis = new BufferedInputStream(zip.getInputStream(entry));
                    while ((count = bis.read(buffer, 0, bufferSize)) != -1) {
                        bos.write(buffer, 0, count);
                    }
                    bos.flush();
                } catch (IOException e) {
                    e.printStackTrace();
                    return false;
                } finally {
                    try {
                        if (bos != null) {
                            bos.flush();
                        }
                        if (bos != null) {
                            bos.close();
                            bos = null;
                        }
                        if (bis != null) {
                            bis.close();
                            bis = null;
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            } else if (!entryFile.mkdirs()) {
                break;
            }
        }//while
        if (zip != null) {
            try {
                zip.close();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
        return true;
    }

    /**
     * 初始化系统相关信息
     */
    private static void initOS() {
        Properties properties = System.getProperties();
        String osName = properties.getProperty("os.name");
        if (!isEmpty(osName)) {
            osName = osName.toLowerCase();
            if (osName.contains("windows")) {
                dir_p = "\\";
            } else {
                dir_p = "/";
            }
        } else {
            dir_p = "/";
        }
    }

    private static String dir_p;

    public static void main(String[] args) throws Exception {
        String unzipFilePath = "D:\\AXYTWorkRecord\\Android\\生产环境全量备份.zip";
        String unzipiTargetDir = "D:\\AXYTWorkRecord\\CD2000";
        ZipUtils.unZip(unzipFilePath, unzipiTargetDir, true);

    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值