java zip解压

前言:zip解压Windows默认是GBK,Mac默认是UTF-8,为了保证都可以解压,就需要根据不同的文件设置不同的编码格式,本文解决方案是根据是否乱码来判断(详见下文)

如果解压过程中不需要操作文件请看方法一(三行解压到本地)

如果解压过程中需要操作文件如网盘中实现在线解压,基本实现设想就是边解压,边创建文件夹(或上传文件)到网盘数据库,看方法二

注:两种方法均引用于其他博客,但由于找不到原文地址了,望有知道的兄弟留言告知,及时加注上

方法一:

maven配置:

        <dependency>
            <groupId>net.lingala.zip4j</groupId>
            <artifactId>zip4j</artifactId>
            <version>1.3.2</version>
        </dependency>

代码:

package com.gxs.test.util;


import net.lingala.zip4j.core.ZipFile;
import net.lingala.zip4j.model.FileHeader;
import java.util.List;

/**
 * 已解决乱码问题
 */
public class UnZipFiles {

    public static void unZip(String zipPath, String destDir) throws Exception {
        ZipFile zipFile = new ZipFile(zipPath);
        zipFile.setFileNameCharset(getEncoding(zipPath));
        zipFile.extractAll(destDir);
    }

    @SuppressWarnings("unchecked")
    private static String getEncoding(String path) throws Exception {
        String encoding = "GBK";
        ZipFile zipFile = new ZipFile(path);
        zipFile.setFileNameCharset(encoding);
        List<FileHeader> list = zipFile.getFileHeaders();
        for (int i = 0; i < list.size(); i++) {
            FileHeader fileHeader = list.get(i);
            String fileName = fileHeader.getFileName();
            if (isMessyCode(fileName)) {
                encoding = "UTF-8";
                break;
            }
        }
        return encoding;
    }

    private static boolean isMessyCode(String str) {
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            // 当从Unicode编码向某个字符集转换时,如果在该字符集中没有对应的编码,则得到0x3f(即问号字符?)
            // 从其他字符集向Unicode编码转换时,如果这个二进制数在该字符集中没有标识任何的字符,则得到的结果是0xfffd
            if ((int) c == 0xfffd) {
                // 存在乱码
                return true;
            }
        }
        return false;
    }



    public static void main(String[] args){
        /**
         * 解压文件
         */
        String zipFile = "E:\\ziptest\\测试1级目录.zip";
        String path = "E:\\ziptest";
        try {
            unZip(zipFile, path);
        } catch (Exception e) {
            e.printStackTrace();
        }
        ;

    }
}


方法二:

代码:

package com.gxs.test.util;

import org.springframework.stereotype.Component;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.charset.Charset;
import java.util.zip.CRC32;
import java.util.zip.CheckedInputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

/**
 * zip压缩工具类
 *  @className: UnzipUtils
 *  @author: gxs
 *  @date: 2021/6/5 9:13
 *  @version: 1.0
 */
@Component
public class UnzipUtil {

    private static final int BUFFER = 1024;
    private static final String CODING_UTF8 = "UTF-8";
    private static final String CODING_GBK = "GBK";

    /**
     * 解压入口方法
     *
     * @param zipPath zip文件物理地址
     * @param unzipPath 解压后存放路径
     * @throws Exception
     */
    public static void decompress(String zipPath, String unzipPath)  throws Exception {
        //解压缩执行方法
        decompressFile(new File(zipPath), new File(unzipPath));
    }

    /**
     * 解压缩执行方法
     *
     * @param srcFile 压缩文件File实体
     * @param destFile 解压路径File实体
     * @throws Exception
     */
    public static void decompressFile(File srcFile, File destFile) throws Exception {
        //创建数据输入流
        CheckedInputStream cis = new CheckedInputStream(new FileInputStream(srcFile), new CRC32());
        //创建压缩输入流
        ZipInputStream zis = new ZipInputStream(cis, Charset.forName(CODING_UTF8));
        //异常捕获的方式判断编码格式
        try {
            //判断代码,如果此代码未抛出异常,则表示编码为UTF-8
            zis.getNextEntry().getName();
        } catch (Exception e) {
            //如果乱码会抛异常,抛异常重新创建输入流,重新设置编码格式
            cis = new CheckedInputStream(new FileInputStream(srcFile), new CRC32());
            zis = new ZipInputStream(cis, Charset.forName(CODING_GBK));
        }
        //解压zip
        decompressZis(destFile, zis);
        //关闭流
        zis.close();

    }

    /**
     * 文件 解压缩执行方法
     *
     * @param destFile 目标文件
     * @param zis ZipInputStream
     * @throws Exception
     */
    private static void decompressZis(File destFile, ZipInputStream zis)   throws Exception {
        ZipEntry entry;
        while ((entry = zis.getNextEntry()) != null) {
            //获取当前的ZIP条目路径
            String dir = destFile.getPath() + File.separator + entry.getName();
            File dirFile = new File(dir);
            //递归检查文件路径,路径上没有文件夹则创建,保证整条路径在本地存在
            fileProber(dirFile);
            //判断是否是文件夹
            if (entry.isDirectory()) {
                //如果是,创建文件夹
                dirFile.mkdirs();
                System.out.println(dirFile.getName());
            } else {
                //如果不是文件夹,数据流输出,生成文件
                decompressFile(dirFile, zis);
            }
            //关闭当前的ZIP条目并定位流
            zis.closeEntry();
        }
    }

    /**
     * 文件探针,当父目录不存在时,创建目录
     * 
     * @param dirFile ZIP条目路径
     */
    private static void fileProber(File dirFile) {
        //获取此路径的父目录
        File parentFile = dirFile.getParentFile();
        //判断是否存在
        if (!parentFile.exists()) {
            // 递归寻找上级目录
            fileProber(parentFile);
            //直至存在,递归执行创建文件夹
            parentFile.mkdir();
        }

    }

    /**
     * 生成文件
     * 
     * @param destFile 目标文件
     * @param zis ZipInputStream
     * @throws Exception
     */
    private static void decompressFile(File destFile, ZipInputStream zis) throws Exception {
        //创建输出流
        BufferedOutputStream bos = new BufferedOutputStream( new FileOutputStream(destFile));
        //转成byte数组
        int count;
        byte[] data = new byte[BUFFER];
        //读取并写入文件
        while ((count = zis.read(data, 0, BUFFER)) != -1) {
            bos.write(data, 0, count);
        }
        //关闭数据流
        bos.close();
    }

    public static void main(String[] args){
        try {
            decompress("E:\\ziptest\\测试1级目录.zip", "E:\\ziptest\\");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值