Java解压/压缩不加密zip文件使用jdk原生方法

Java解压/压缩不加密zip文件,使用jdk原生方法

  • 使用要求:推荐JDK8,理论上JDK7以上
  • 存在问题:异常处理不是特别完善
  • 代码中带有大量注释。
  • 需要完善的zip功能可以使用zip4j

使用方法

工具类取名ZIPUtil,规则:解压生成同名文件夹。压缩生成同名zip文件。

//解压,传入绝对路径
ZIPUtil.decompression("D://WangPan2.zip");
//压缩,传入绝对路径
ZIPUtil.compress("D://aaaa你.txt");

工具类代码

import java.io.*;
import java.nio.charset.Charset;
import java.nio.file.*;
import java.util.Enumeration;
import java.util.List;
import java.util.stream.Collectors;
import java.util.zip.*;

/**
 * 可以使用工具包zip4j
 */
public class ZIPUtil {
    /**
     * 解压zip压缩包
     *
     * @param zipFileAddress 压缩包路径,绝对路径
     * @throws IOException
     */
    public static void decompression(String zipFileAddress) throws ZipException {
        Path zipFilePath = Paths.get(zipFileAddress);
        if (!Files.exists(zipFilePath)) {
            throw new ZipException("压缩包不存在:" + zipFileAddress);
        }
        //获取文件名称,去除掉后缀.zip
        String rootDirName = zipFilePath.getFileName().toString().replaceAll("\\.zip$", "");
        //生成解压路径,与压缩包同级目录下的同名文件夹
        Path decompressionPath = zipFilePath.resolveSibling(rootDirName);
        if (Files.exists(decompressionPath)) {
            throw new ZipException("解压文件同名文件夹已存在");
        }
        try {
            //读取压缩包,压缩包内有中文使用GBK才能让中文显示正确
            ZipFile zipFile = new ZipFile(zipFilePath.toString(), Charset.forName("gbk"));
            //压缩包内所有压缩文件目录
            Enumeration allEntries = zipFile.entries();
            while (allEntries.hasMoreElements()) {
                ZipEntry zipEntry = allEntries.nextElement();
                System.out.println("解压文件目录:" + zipEntry.getName());
                if (zipEntry.isDirectory()) {
                    //创建文件夹
                    Files.createDirectories(decompressionPath.resolve(zipEntry.getName()));
                } else {
                    //压缩包内压缩文件解压路径
                    Path entrieFilePath = decompressionPath.resolve(zipEntry.getName());
                    //父路径不存在则创建父路径,按照压缩包目录生成规则,目录会比目录中文件优先生成,但是为了防止意外,增加目录判断
                    if (!Files.exists(entrieFilePath.getParent())) {
                        Files.createDirectories(entrieFilePath.getParent());
                    }
                    //创建解压文件
                    Files.createFile(entrieFilePath);
                    //输出流向输入流传数据。嵌套一层try用于自动关闭流。
                    try (BufferedInputStream i = new BufferedInputStream(zipFile.getInputStream(zipEntry));
                         BufferedOutputStream o = new BufferedOutputStream(new FileOutputStream(entrieFilePath.toString()));) {
                        byte[] b = new byte[1024];
                        int r;
                        while ((r = i.read(b, 0, b.length)) != -1) {
                            o.write(b, 0, r);
                        }
                        o.flush();
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
            throw  new ZipException(e.getMessage());
        }
    }

    /**
     * 压缩文件或文件夹
     *
     * @param fileAddress 文件或文件夹的绝对地址
     * @throws IOException
     */
    public static void compress(String fileAddress) throws ZipException {
        Path waitCompressPath = Paths.get(fileAddress);
        //判断文件或文件夹是否存在
        if (!Files.exists(waitCompressPath)) {
            throw new ZipException("待压缩文件或文件夹不存在:" + fileAddress);
        }
        //判断是文件还是文件夹
        if (Files.isDirectory(waitCompressPath)) {
            //压缩文件夹
            compressFolder(waitCompressPath);
        } else {
            //压缩文件
            compressFile(waitCompressPath);
        }
        System.out.println("压缩完成,被压缩文件:" + fileAddress);
    }

    /**
     * 压缩文件夹
     *
     * @param waitCompressFilePath 文件绝对地址
     * @throws ZipException
     */
    private static void compressFile(Path waitCompressFilePath) throws ZipException {
        //解压文件名称,去除末尾的.xxx后缀
        String removeSuffixFileName = waitCompressFilePath.getFileName().toString().replaceAll("\\.[^\\..]+$", "");
        Path zipFilePath = waitCompressFilePath.resolveSibling(removeSuffixFileName + ".zip");
        if (Files.exists(zipFilePath)) {
            throw new ZipException("当前目录下,存在与需要压缩文件同名的.zip文件 :" + zipFilePath);
        }
        try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(waitCompressFilePath.toFile())); ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFilePath.toString())));) {
            //创建压缩文件,上方在new FileOutputStream时会自动创建文件
//            Files.createFile(zipFilePath);
            //向zip中放入压缩文件
            out.putNextEntry(new ZipEntry(waitCompressFilePath.getFileName().toString()));
            //从输入流向输出流中读取数据
            byte[] bytes = new byte[1024];
            int read;
            while ((read = in.read(bytes)) != -1) {
                out.write(bytes, 0, read);
            }
            out.flush();
            //关闭当前压缩文件
            out.closeEntry();
        } catch (IOException e) {
            e.printStackTrace();
            //未知io错误
            throw new ZipException(e.getMessage());
        }

    }

    /**
     * 压缩文件夹
     *
     * @param waitCompressFilePath 文件夹绝对地址
     * @throws ZipException
     */
    private static void compressFolder(Path waitCompressFilePath) throws ZipException {
        //创建同名压缩文件以.zip结尾
        Path compressZipFilePath = waitCompressFilePath.resolveSibling(waitCompressFilePath.getFileName().toString() + ".zip");
        if (Files.exists(compressZipFilePath)) {
            throw new ZipException("压缩文件夹或文件同名.zip压缩包已存在。");
        }
        try (ZipOutputStream zipout = new ZipOutputStream(new FileOutputStream(compressZipFilePath.toString()));) {
            //创建压缩文件,上方new FileOutputStream时会创建对应文件
//            Files.createFile(compressZipFilePath);
            //遍历文件夹,获取压缩条目
            List zipEntries = ZIPUtil.getZipEntries(waitCompressFilePath);
            for (Path zipEntryPath : zipEntries) {
                //嵌套一层try确保流在任何时候都会被关闭
                try (BufferedInputStream binput = new BufferedInputStream(new FileInputStream(waitCompressFilePath.resolve(zipEntryPath).toString()));) {
                    //输入流向输出流传数据
                    byte[] bytes = new byte[1024];
                    int read;
                    ZipEntry zipEntry = new ZipEntry(zipEntryPath.toString());
                    zipout.putNextEntry(zipEntry);
                    while ((read = binput.read(bytes, 0, bytes.length)) != -1) {
                        zipout.write(bytes, 0, read);
                    }
                    zipout.flush();
                    zipout.closeEntry();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
            //未知io错误
            throw new ZipException(e.getMessage());
        }
    }

    /**
     * 根据需要压缩的文件夹,生成zip总条目
     *
     * @param path 需要打zip包的文件夹绝对路径,如:D://WangPan
     * @return 返回类型为列表,列表内path为相对于打文件夹的相对路径
     * @throws IOException
     */
    private static List getZipEntries(Path path) throws IOException {
//        List collect = Files.walk(path).map(p -> path.relativize(p)).filter(p -> !"".equals(p.toString())).collect(Collectors.toList());
        List collect = Files.walk(path).filter(p -> !Files.isDirectory(p)).map(p -> path.relativize(p)).collect(Collectors.toList());
        return collect;
    }
}

你可能感兴趣的:(踩坑笔记,java)