java解压zip包(包括空文件夹),并获取解压的文件树对象

记录一个java解压zip包的代码,没啥难度,就主要下面两个注意点:

  • zip大多数是windows系统下,所以使用GBKCharset.forName("GBK")格式,不然会报错
  • 空文件夹不能用file.isDirectory()处理,网上大多数文档都是这么处理会有问题,具体详见代码
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.charset.Charset;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

@RestController
@RequestMapping("/test")
public class ZipUploadController {


    @PostMapping(value = "/uploadZip", headers = "content-type=multipart/*")
    public String uploadZip(@RequestParam("zipFile") MultipartFile zipFile) throws Exception {
        //解压后存放的目标文件夹
        String path = "C:/Users/Administrator/Desktop/zipTest/";
        File newFile = new File(path + zipFile.getOriginalFilename());
        zipFile.transferTo(newFile);
        zipUncompress(newFile, path);
        return "success";
    }

    /**
     * zip文件解压
     */
    public static void zipUncompress(File srcFile, String destDirPath) throws Exception {
        // 判断源文件是否存在
        if (!srcFile.exists()) {
            throw new Exception(srcFile.getPath() + "所指文件不存在");
        }
        ZipFile zipFile = new ZipFile(srcFile, Charset.forName("GBK"));//创建压缩文件对象
        //开始解压
        Enumeration<?> entries = zipFile.entries();
        while (entries.hasMoreElements()) {
            ZipEntry entry = (ZipEntry) entries.nextElement();
            // 如果是文件夹,就创建个文件夹
            if (entry.getName().endsWith("/") || entry.getName().endsWith("\\")) {
                File dir = new File(destDirPath +
                        entry.getName().substring(0, entry.getName().length() - 1));//空文件的结尾带/
                if (!dir.exists()) {
                    dir.mkdirs();
                }
            } else {
                InputStream is = null;
                FileOutputStream fos = null;
                try {
                    // 如果是文件,就先创建一个文件,然后用io流把内容copy过去
                    File targetFile = new File(destDirPath + "/" + entry.getName());
                    // 保证这个文件的父文件夹必须要存在
                    if (!targetFile.getParentFile().exists()) {
                        targetFile.getParentFile().mkdirs();
                    }
                    targetFile.createNewFile();
                    // 将压缩文件内容写入到这个文件中
                    is = zipFile.getInputStream(entry);
                    fos = new FileOutputStream(targetFile);
                    int len;
                    byte[] buf = new byte[1024];
                    while ((len = is.read(buf)) != -1) {
                        fos.write(buf, 0, len);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    // 关流顺序,先打开的后关闭
                    if(fos != null){
                        fos.close();
                    }
                    if(is != null){
                        is.close();
                    }
                }
            }
        }

    }
}

上面是上传并解压zip包,解压后拿到解压的文件File,这里提供一个自己临时写的工具类,可以把解压后的文件解析到文件树对象中,方便获取每一级的文件和下级文件

import com.google.common.collect.Lists;
import lombok.Data;
import org.apache.commons.collections.CollectionUtils;

import java.io.File;
import java.util.List;

/**
 * 文件树
 *
 * @author zx
 */
@Data
public class FileTreeNode {

    /**
     * 文件名称
     */
    private String name;

    /**
     * 文件内容
     */
    private File file;

    /**
     * 当前文件所属层级
     */
    private int level;

    /**
     * 类型  1:文件夹  2:文件
     */
    private int type;

    /**
     * 下级文件
     */
    private List<FileTreeNode> nextNodes;

    /**
     * 是否有下级
     */
    public boolean hasNext() {
        return nextNodes != null && nextNodes.size() > 0;
    }

    /**
     * 是不是文件夹
     */
    public boolean isDirectory() {
        return type == 1;
    }

    /**
     * 是不是文件
     */
    public boolean isFile() {
        return type == 2;
    }


    /**
     * 加载这个文件下的文件树  包括文件夹和文件
     *
     * @param file         要加载的文件
     * @param readMaxLevel 最大读多少层   该值小于1则表示有多少层读取多少层
     * @return
     */
    public static FileTreeNode readZipFile(File file, int readMaxLevel) {
        return readZipFile(file, 0, readMaxLevel);
    }

    private static FileTreeNode readZipFile(File file, int fileLevel, int readMaxLevel) {
        if (readMaxLevel > 0 && fileLevel > readMaxLevel) {
            return null;
        }

        // 取得文件目录中所有文件的File对象数组
        File[] files = file.listFiles();
        if (files == null || files.length < 1) {
            return null;
        }

        FileTreeNode fileTreeNode = new FileTreeNode();
        int i = file.getName().lastIndexOf(".");
        if (i >= 0) {
            fileTreeNode.setName(file.getName().substring(0, i));
        } else {
            fileTreeNode.setName(file.getName());
        }
        fileTreeNode.setFile(file);
        fileTreeNode.setLevel(fileLevel);
        if (file.isDirectory()) {
            //文件夹
            fileTreeNode.setType(1);
        } else {
            //文件
            fileTreeNode.setType(2);
        }

        if (CollectionUtils.isEmpty(fileTreeNode.getNextNodes())) {
            fileTreeNode.setNextNodes(Lists.newArrayList());
        }

        fileLevel++;
        // 遍历file数组
        for (File nextFile : files) {
            FileTreeNode nextTreeNode = new FileTreeNode();
            int x = nextFile.getName().lastIndexOf(".");
            if (x >= 0) {
                nextTreeNode.setName(nextFile.getName().substring(0, x));
            } else {
                nextTreeNode.setName(nextFile.getName());
            }
            nextTreeNode.setFile(nextFile);
            nextTreeNode.setLevel(fileLevel);
            if (nextFile.isDirectory()) {
                nextTreeNode.setType(1);
                // 递归子目录
                FileTreeNode fileTreeNode1 = readZipFile(nextFile, fileLevel, readMaxLevel);
                if (fileTreeNode1 != null) {
                    fileTreeNode.getNextNodes().add(fileTreeNode1);
                }
            } else {
                nextTreeNode.setType(2);
                fileTreeNode.getNextNodes().add(nextTreeNode);
            }
        }
        return fileTreeNode;
    }

    public static void main(String[] args) {
        FileTreeNode fileTreeNode = FileTreeNode.readZipFile(new File("C:\\Users\\Administrator\\Desktop\\xxxxxx"), 0);
        System.out.println(JSONObject.toJSONString(fileTreeNode));
    }

}

解析文件夹并生成文件树对象的这个代码是自己随便写的,存在问题欢迎指正,目前我使用中未发现问题
当然你也可以直接使用工具类:org.apache.commons.io的FileUtils.listFilesAndDirs()

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值