在线压缩和解压缩

  1. 在线压缩和解压缩
    1. 工具类

在线压缩和解压缩

最近在做服务端的文件压缩与解压缩操作,下面是一些可能会用到的工具方法。

服务端操作zip压缩包可以使用java提供的zip类相关方法。

涉及到文件流输出,文件流写入。

工具类

package pers.os467.support.utils.zip;


import pers.os467.support.utils.IOUtils;

import java.io.*;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

/**
 * ZIP工具类
 * author: os467
 */
public class ZipFileUtils {


    /**
     * 获取zip条目所属目录条目名称
     * @param name
     * @return
     */
   public static String getEntryDirName(String name){
       if (name.endsWith("/")){
           //查询其上一级条目
           String last = name.substring(0, name.lastIndexOf("/"));
           if (!last.contains("/")){
               //无上一级目录
               return null;
           }else {
               //返回目录名
               return last.substring(0,last.lastIndexOf("/")+1);
           }
       }else {
           if (name.contains("/")){
               return name.substring(0, name.lastIndexOf("/")+1);
           }else {
               //无上一级目录
               return null;
           }
       }
   }


    /**
     * 解压缩,保存文件夹结构
     * @param zipFile
     * @param outPutPath
     */
    public static void unzip(ZipFile zipFile,String outPutPath){

        File file = new File(outPutPath);
        if (file.exists()){
            if (!file.isDirectory()){
                throw new RuntimeException("output path not a directory");
            }
        }else {
            file.mkdirs();
        }

        Enumeration<? extends ZipEntry> entries = zipFile.entries();
        //将zip文件集合读出
        while (entries.hasMoreElements()) {
            ZipEntry zipEntry = entries.nextElement();
            if (zipEntry.isDirectory()){
                continue;
            }

            //非目录
            String dirs = zipEntry.getName().substring(0, zipEntry.getName().lastIndexOf("/") + 1);
            File df = new File(outPutPath + File.separator + dirs);
            df.mkdirs();

            File outPut = new File(outPutPath + File.separator + zipEntry.getName());
            writeEntryToFile(zipFile, zipEntry, outPut);
        }

    }

    /**
     * 将zip内部条目解压缩到指定文件
     * @param zipFile
     * @param zipEntry
     * @param outPut
     */
    public static void writeEntryToFile(ZipFile zipFile, ZipEntry zipEntry, File outPut) {
        FileOutputStream outputStream = null;
        try {
            outputStream = new FileOutputStream(outPut);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        try {
            InputStream inputStream = zipFile.getInputStream(zipEntry);
            IOUtils.copy(inputStream,outputStream);
        } catch (IOException ioException) {
            ioException.printStackTrace();
        }finally {
            try {
                outputStream.close();
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        }
    }


    /**
     * 压缩文件
     * @param files 条目 : 输出文件
     * @param zipFileOutPutPath 文件输出路径
     */
    public static void zipFile(Map<String, File> files,String zipFileOutPutPath){
        //压缩文件
        try {
            FileOutputStream fileOutputStream = new FileOutputStream(zipFileOutPutPath);
            zipFilesToOutPutStream(files,fileOutputStream);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException ioException) {
            ioException.printStackTrace();
        }
    }

    /**
     * 将输出流包装为zip输出流并按照文件结构映射打包文件
     * @param files key为zip中的路径,分隔符必须使用"/" value为文件对象,若为null如果是目录则创建空目录
     *              例如
     *              新建文件夹1/ -> null
     *              新建文件夹1/新建文件夹2 -> null
     *              新建文件夹/1.txt  -> new File(".../1.txt")
     *              新建文件夹1/新建文件夹2/2.txt -> new File(".../2.txt")
     * @param out 输出流
     * @throws IOException
     */
    public static void zipFilesToOutPutStream(Map<String, File> files, OutputStream out) throws IOException {
        if (files.size() == 0){
            //创建空zip
            try (ZipOutputStream zos = new ZipOutputStream(out)){//do nothing...
                }
            return;
        }
        // 创建一个ZipOutputStream对象,它将用于写入压缩数据
        try (ZipOutputStream zos = new ZipOutputStream(out)) {
            // 遍历文件映射
            for (Map.Entry<String, File> entry : files.entrySet()) {
                // 获取文件的ZIP路径和对应的文件对象
                String name = entry.getKey();
                File file = entry.getValue();

                //如果是目录则创建空目录 例如name = dir1/dir2/
                if (file == null) {
                    zos.putNextEntry(new ZipEntry(name));
                    zos.closeEntry();
                    continue;
                }

                // 如果文件对象不是一个文件,抛出异常
                if (!file.isFile()) {
                    throw new IllegalArgumentException("Only files are supported");
                }

                // 创建一个新的ZIP条目并将其添加到ZIP输出流中  例如: name = dir1/dir2/fileName
                // 这里的name就是文件在压缩包中的路径,包括多级目录
                zos.putNextEntry(new ZipEntry(name));

                // 创建一个输入流来读取文件的内容
                try (InputStream in = new FileInputStream(file)) {
                    // 创建一个缓冲区
                    byte[] buffer = new byte[1024];
                    int len;
                    // 读取文件内容并写入ZIP输出流
                    while ((len = in.read(buffer)) != -1) {
                        zos.write(buffer, 0, len);
                    }
                }

                // 关闭当前ZIP条目,使其写入ZIP文件
                zos.closeEntry();
            }
        }
    }

    /**
     * 获取zip条目文件名
     * @param name
     * @return
     */
    public static String getEntryFileName(String name) {
        if (name.endsWith("/")){
            //文件夹
            String s = name.substring(0, name.length() - 1);
            return s.substring(s.lastIndexOf("/") + 1);
        }else {
            //非文件夹
            if (name.contains("/")){
                return name.substring(name.lastIndexOf("/") + 1);
            }else {
                return name;
            }
        }
    }


    /**
     * 集合去重计算文件总数量
     * @param zipFile
     * @return
     */
    public static Integer countFileNum(ZipFile zipFile) {
        Set<String> set = new HashSet<>();
        Enumeration<? extends ZipEntry> entries = zipFile.entries();
        while (entries.hasMoreElements()) {
            ZipEntry zipEntry = entries.nextElement();
            String name = zipEntry.getName();
            if (name.contains("/")){
                String[] path = name.split("/");
                String build = "";
                for (int i = 0; i < path.length - 1; i++) {
                    build += path[i] + "/";
                    set.add(build);
                }
            }
            set.add(name);
        }
        return set.size();
    }


}

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以邮件至 1300452403@qq.com

文章标题:在线压缩和解压缩

字数:1.1k

本文作者:Os467

发布时间:2024-02-15, 16:52:31

最后更新:2024-02-15, 16:52:41

原始链接:https://os467.github.io/2024/02/15/%E5%9C%A8%E7%BA%BF%E5%8E%8B%E7%BC%A9%E4%B8%8E%E8%A7%A3%E5%8E%8B%E7%BC%A9/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

×

喜欢就点赞,疼爱就打赏