zip4j解压zip时,出现中文乱码,看了下,zip4j解压时支持设置文件编码,我们只需要识别文件是不是utf-8编码,如果不是utf-8就使用gbk解压,但是这个判断没有100%准确的方式,我试过通过字节流的bom标记去判断,但是文件不一定有bom字节,所以不适用。
网上最多的判断方式是使用第三方jar工具cpdetecpor或juniversalchardet,但是这两种方式我都尝试过,juniversalchardet无法判断出文件编码,而cpdetecpor可以得到一个判断结果,但是也不准确,我经过一两天的探索查找,找到了一个比较靠谱的方式:
/*** 解压*/@SneakyThrowspublic static void unzipFile(String zipFilePath, String destFilePath, String password) {ZipFile zipFile = null;try {zipFile = new ZipFile(zipFilePath);zipFile.setCharset(StandardCharsets.UTF_8);List<FileHeader> headers = zipFile.getFileHeaders();//判断文件名是否有乱码,有乱码,将编码格式设置成GBKif (isRandomCode(headers)) {log.info("使用UTF-8解压文件【{}】时乱码,尝试使用GBK重新解压",zipFilePath);zipFile.close();zipFile = new ZipFile(zipFilePath);zipFile.setCharset(Charset.forName("GBK"));}if (!zipFile.isValidZipFile()) {throw new VerifyException("压缩文件不合法,可能被损坏.");}if (zipFile.isEncrypted() && StringTool.isNotBlank(password)) {//加密zip,且输入的密码不为空,直接进行解密。zipFile.setPassword(password.toCharArray());}FileTool.createDir(destFilePath);zipFile.extractAll(destFilePath);}finally {IOUtils.closeQuietly(zipFile,null);}}private static boolean isRandomCode(List<FileHeader> fileHeaders) {for (FileHeader fileHeader : fileHeaders) {boolean canEnCode = Charset.forName("GBK").newEncoder().canEncode(fileHeader.getFileName());if (!canEnCode) {//canEnCode为true,表示不是乱码。false.表示乱码。是乱码则需要重新设置编码格式return true;}}return false;}
我们先使用utf-8读取zip里面的文件名,然后判断文件名是否能使用gbk进行编码,如果不能,我们就用utf-8解压,如果gbk可以编码,就使用gbk进行解压