一、兼容解压文件GBK和UTF-8两种编码

3,019 阅读1分钟

1、问题

linux下面压缩文件默认用utf-8,windows下面是GBK。乱码主要是由于不同的字符集相互转换导致的,理论上各个字符的编码规则是不同的,是不能相互转换的,所以根本解决乱码的方法就是不要转换编码方式,编码方式前后统一。

2、分析

源代码,需要兼容GBK和UTF-8两种编码方式

public Integer synBatchUploadEmployees(MultipartFile file) {
    //此处解压默认是UTF-8
    ZipArchiveInputStream zipInputStream = new ZipArchiveInputStream(new ByteArrayInputStream(file.getBytes()));
    ZipArchiveEntry zipArchiveEntry = null;
    while ((zipArchiveEntry = zipArchiveInputStream.getNextZipEntry()) != null) {
        System.out.println(zipArchiveEntry.getName());
    }
}

3、方案

判断上传的文件编码类型

  • 依赖包pom.xml
<dependency>
    <groupId>net.lingala.zip4j</groupId>
    <artifactId>zip4j</artifactId>
    <version>2.2.8</version>
</dependency>

  • 代码
public static void getMultipartFileEncoding(MultipartFile multipartFile) throws Exception {
    String path = "/Users/spark/Desktop/data";
    if (!new File(path).exists()) {
        new File(path).mkdirs();
    }

    String destPath = "/Users/spark/Desktop/data/" + UUID.randomUUID().toString() + multipartFile.getName();
    File dest = new File(destPath);
    multipartFile.transferTo(dest);
    System.out.println(Charset.forName(getEncoding(destPath)));
    dest.delete();
}

@SuppressWarnings("unchecked")
private static String getEncoding(String path) throws Exception {
    String encoding = "GBK";
    ZipFile zipFile = new ZipFile(path);
    zipFile.setCharset(Charset.forName(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;
}

4、方案弊端

  • 需要临时保存压缩文件,暂用磁盘空间。
  • 需要遍历文件,若压缩文件中文件过多,而中文命名乱码过少,增加请求的耗时。