java解压ZIP文件并解决中文乱码问题

场景:解压xxxx.zip文件(如果zip文件里面嵌套zip,市面上工具基本不支持,自己写个递归方法即可),中文文件名出现乱码

工具:zip4j(默认编码集UTF-8)

乱码原因:

        ZIP格式在不同平台上使用不同软件压缩:

                       1. Windows下使用WinRAR、好压、快压、百度压缩、360等工具压缩的文件 特点:文件名为GBK编码

                       2. 使用Linux、MacOS等系统压缩的zip文件 特点:文件名为UTF-8编码

maven配置信息:

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

解决方法:(直接上代码)


import com.google.common.collect.Lists;
import net.lingala.zip4j.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.FileHeader;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

/**
 * @author Angelo
 * @date 2021/4/12 16:44
 **/
public class ZipUtils {

    private static final Logger logger = LoggerFactory.getLogger(ZipUtils.class);

    private final static String RIGHT_SLASH = "/";

    private final static String DOUBLE_LEFT_SLASH = "\\\\";

    private final static String LEFT_SLASH = "\\";

    private final static String CHARSET_GBK = "GBK";
    /**
     * 根据文件全路径将zip文件解压到一个文件路径下
     * @param realPath
     * @param dest
     */
    public static List<UnZipInfo> unzip(String realPath, String dest){
        try {
            logger.info("解压开始:"+System.currentTimeMillis());
            List<UnZipInfo> files = Lists.newArrayList();
            ZipFile zipFile = new ZipFile(realPath);
            zipFile.setCharset(Charset.forName(CHARSET_GBK));
            zipFile.extractAll(dest);
            // 获取ZIP中所有文件的FileHeader,以便后面对zip中文件进行遍历
            List<FileHeader> list = zipFile.getFileHeaders();
            logger.info("解压结束:"+System.currentTimeMillis());
            list.forEach(fileHeadr->{
                String fileName = fileHeadr.getFileName();
                //zip压缩文件里面的文件列表
                //如果是目录不做处理
                if (fileName.endsWith(RIGHT_SLASH) || fileName.endsWith(DOUBLE_LEFT_SLASH) || fileName.endsWith(LEFT_SLASH)){
                    logger.info("这是一个文件夹:"+fileName);
                }else {
                    //如果不是文件夹,将文件信息放入文件列表容器
                    UnZipInfo unZipInfo = new UnZipInfo();
                    unZipInfo.setFileOriginName(fileName);
                    unZipInfo.setRealAllPath(dest+File.separator+fileName);
                    files.add(unZipInfo);
                }
            });
            return files;
        } catch (ZipException e) {
            logger.error("unzip file[{}] has error", realPath, e);
        }
        return null;
    }


    /**
     * 前端传入File类型文件
     * @param multipartFile
     */
    public static List<UnZipInfo> unzipByFile(MultipartFile multipartFile){
        try {
            logger.info("解压开始:"+System.currentTimeMillis());
            List<UnZipInfo> files = Lists.newArrayList();
            //将存放在服务器的文件路径
            String dateStr = String.valueOf(System.currentTimeMillis());
            String tempDirectory = FileUtils.getTempDirectoryPath();
            //Windows系统文件路径
            String filePath = tempDirectory+File.separator+"Housing_System_Zip_"+dateStr;
            logger.info("临时文件目录:"+tempDirectory+";压缩文件解压路径:"+filePath);
            //multipartFile转成File
            File file = new File(filePath+File.separator+multipartFile.getOriginalFilename());
            FileUtils.copyInputStreamToFile(multipartFile.getInputStream(), file);
            ZipFile zipFile = new ZipFile(file);
            if (!testEncoding(filePath + File.separator + multipartFile.getOriginalFilename(), StandardCharsets.UTF_8)){
                zipFile.setCharset(Charset.forName(CHARSET_GBK));
            }
            zipFile.extractAll(filePath);
            // 获取ZIP中所有文件的FileHeader,以便后面对zip中文件进行遍历
            List<FileHeader> list = zipFile.getFileHeaders();
            list.forEach(fileHeadr->{
                String fileName = fileHeadr.getFileName();
                //zip压缩文件里面的文件列表
                //如果是目录不做处理
                if (fileName.endsWith(RIGHT_SLASH) || fileName.endsWith(DOUBLE_LEFT_SLASH) || fileName.endsWith(LEFT_SLASH)){
                    logger.info("这是一个文件夹:"+fileName);
                }else {
                    //如果不是文件夹,将文件信息放入文件列表容器
                    UnZipInfo unZipInfo = new UnZipInfo();
                    unZipInfo.setFileOriginName(fileName);
                    unZipInfo.setRealAllPath(filePath+File.separator+fileName);
                    files.add(unZipInfo);
                }
            });
            logger.info("解压结束:"+System.currentTimeMillis());
            return files;
        } catch (ZipException e) {
            logger.error("unzipByFile file[{}] has error", multipartFile, e);
        } catch (IOException e) {
            logger.error("multipartFile to File has error", e);
        }
        return null;
    }

    /**
     * 文件字符集判断
     * @param filepath
     * @param charset
     * @return
     * @throws FileNotFoundException
     */
    private static boolean testEncoding(String filepath, Charset charset) throws FileNotFoundException {
        FileInputStream fis = new FileInputStream(new File(filepath));
        BufferedInputStream bis = new BufferedInputStream(fis);
        ZipInputStream zis = new ZipInputStream(bis, charset);
        ZipEntry zn = null;
        try {
            while ((zn = zis.getNextEntry()) != null) {
                logger.info("check file charset");
            }
        } catch (Exception e) {
            return false;
        }finally {
            try {
                zis.close();
                bis.close();
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return true;
    }
}

 


版权声明:本文为booominng原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。