压缩流ZipOutputStream和解压流ZipInputStream

压缩流ZipOutputStream和解压流ZipInputStream

压缩流解压流

介绍

压缩流和解压流是在文件处理中常用的功能,用于将文件或文件夹进行压缩和解压缩操作。本文将介绍压缩流和解压流的基本概念、常用API和案例示例。

压缩流

ZipOutputStream

ZipOutputStream是Java中用于创建ZIP文件的输出流。它提供了一系列方法来添加文件或文件夹到ZIP文件中,并可以设置压缩级别和压缩方法。

常用API
方法 描述
ZipOutputStream 创建新的ZIP输出流
close 关闭ZIP输出流和正在过滤的流
closeEntry 关闭当前ZIP条目并定位流以写入下一个条目
finish 完成写入ZIP输出流的内容,无需关闭底层流
putNextEntry 开始写入新的ZIP文件条目并将流定位到条目数据的开始处
setComment 设置ZIP文件注释
setLevel 为后续的DEFLATED条目设置压缩级别
setMethod 设置用于后续条目的默认压缩方法
write 将字节数组写入当前ZIP条目数据

补充资料:

解压流

ZipInputStream

ZipInputStream是Java中用于读取ZIP文件的输入流。它提供了一系列方法来读取ZIP文件中的条目,并可以跳过或关闭当前条目。

常用API
方法 描述
ZipInputStream 创建新的ZIP输入流
available 在EOF到达当前条目数据后,返回0;否则,始终返回1
close 关闭此输入流并释放与此流关联的所有系统资源
closeEntry 关闭当前ZIP条目并定位流以读取下一个条目
createZipEntry 为指定条目名称创建一个新的ZipEntry对象
getNextEntry 读取下一个ZIP文件条目并将流定位到该条目数据的开始处
read 从当前ZIP条目读入字节数组
skip 跳过当前ZIP条目中指定的字节数

补充资料:

案例

/**
     * 获取指定文件夹中所有文件的路径列表
     *
     * @param path 源文件夹地址
     * @return 返回Map<String, Boolean>,String 路径|Boolean 判断是否是文件(true 文件|false 文件夹)
     */
    public static Map<String, Boolean> getFileFolderPathMap(String path) {
        // 初始化路径列表
        Map<String, Boolean> map = new HashMap<>();
        // 遍历源文件夹中的所有文件
        for (String file : new File(path).list()) {
            // 构造当前文件的路径
            String paths = path + '\\' + file;
            // 如果当前文件是文件夹,则递归获取该文件夹中的所有文件
            // 并将其文件夹路径添加到路径列表中
            if (new File(paths).isDirectory()) {
                map.put(paths, false);
                map.putAll(getFileFolderPathMap(paths));
            } else {
                // 如果当前文件是普通文件,则将其路径添加到路径列表中
                map.put(paths, true);
            }
        }
        // 返回路径列表
        return map;
    }

    /**
     * 压缩文件夹
     *
     * @param folderPath 源路径
     * @param zipPath    压缩包存放路径/压缩包名称(不需要".zip"后缀)
     * @throws IOException
     */
    public static void zipOutputFolder(String folderPath, String zipPath) throws IOException {
        // 创建压缩流,传入文件输出流
        ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(zipPath + ".zip"));
        // 获取指定文件夹中所有文件的路径列表
        Map<String, Boolean> map = getFileFolderPathMap(folderPath);

        // 遍历路径列表
        for (String paths : map.keySet()) {
            // 判断是否是文件
            if (map.get(paths)) {
                // 在zip流中创建一个ZIP条目,接受一个 ZipEntry 对象作为参数
                // 获取相对于 readPath 的相对路径,作为新的 ZipEntry 的名称
                zipOutputStream.putNextEntry(new ZipEntry(paths.replace(folderPath + "\\", "")));
                // 创建一个文件输入流,用于写入压缩流
                FileInputStream inputStream = new FileInputStream(paths);
                // 创建一个长度为文件长度的字节数组
                byte[] bytes = new byte[(int) new File(paths).length()];
                // 输入流中读取数据到字节数组
                if (inputStream.read(bytes) != -1) {
                    // 将文件数据写入压缩流
                    zipOutputStream.write(bytes);
                }
                inputStream.close();
            }
        }

        zipOutputStream.close();
    }

    /**
     * 解压文件夹
     *
     * @param folderPath 解压的目标路径(不需要"\\"后缀)
     * @param zipPath    压缩包存放路径/压缩包名称(不需要".zip"后缀)
     */
    public static void zipInputFolder(String folderPath, String zipPath) throws IOException {
        // 添加文件夹路径和ZIP文件扩展名
        folderPath = folderPath + "\\";
        zipPath = zipPath + ".zip";

        // 创建ZIP输入流
        ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(zipPath));
        ZipEntry zipEntry;

        // 逐个解压ZIP条目
        while ((zipEntry = zipInputStream.getNextEntry()) != null) {
            // 构造ZIP条目对应的文件对象
            File file = new File(folderPath + zipEntry.getName());
            if (!file.getParentFile().exists()) {
                // 判断解压后文件的父目录是否存在,如果不存在,则使用 mkdirs() 方法创建该目录。这样确保解压后的文件可以被正确地存储在对应的目录中。
                file.getParentFile().mkdirs();
            }

            // 创建输出流和输入流
            OutputStream outputStream = new FileOutputStream(file);
            InputStream inputStream = new ZipFile(zipPath).getInputStream(zipEntry);

            // 逐个读取字节并写入文件
            byte[] bytes = new byte[1024];
            int length = 0;
            while ((length = inputStream.read(bytes)) != -1) {
                outputStream.write(bytes, 0, length);
            }
            // 逐个读取字节并写入文件
            outputStream.close();
            inputStream.close();
        }
        // 关闭ZIP输入流
        zipInputStream.close();
    }