Java开发 — 文件编码导致的中文乱码问题的通用解决方法

  1. Java读取文件时,可以使用文件流;若文件格式为csv,也可以使用opencsv等库进行读写。但是在涉及到中文时,常常出现乱码问题,这是由于文件的编码和读取时使用的文件流的编码不一致导致的。
  2. 涉及中文时,我们通常使用“UTF-8”,“gbk”等常见的编码格式进行文件的存储。正常情况下,是可以顺利存取的。但是在特殊情况如所使用的wps、excel版本问题,存取、另存、修改后保存等操作后,文件编码改变,且不为常见的“UTF-8”,“gbk”等格式,代码读取时则会出现乱码现象。
  3. 在网络上搜索并研究后,我发现了一种万全的解决方法:读取时检测文件的编码类型,使用该编码类型进行文件流的初始化,后续进行文件的读写时,编码则固定为原来格式,且可以适配所有可识别的编码,无需局限于常见的“UTF-8”,“gbk”等格式。

下面是相关样例

//此处的file为MultipartFile的对象,若为普通的file对象,则可以使用下面的getMultipartFile方法进行转换

       // 解析文件
       byte[] bytes = file.getBytes();
       String encoding = getEncoding(bytes);

     /**
     * 获取文件编码类型
     *
     * @param bytes 文件bytes数组
     * @return 编码类型
     */
    public static String getEncoding(byte[] bytes) {
        String defaultEncoding = "UTF-8";
        UniversalDetector detector = new UniversalDetector(null);
        detector.handleData(bytes, 0, bytes.length);
        detector.dataEnd();
        String encoding = detector.getDetectedCharset();
        detector.reset();
        if (encoding == null) {
            encoding = defaultEncoding;
        }
        return encoding;
    }

    public static MultipartFile getMultipartFile(File file) {
        FileItem item = new DiskFileItemFactory().createItem("file"
                , MediaType.MULTIPART_FORM_DATA_VALUE
                , true
                , file.getName());
        try (InputStream input = new FileInputStream(file);
             OutputStream os = item.getOutputStream()) {
            // 流转移
            IOUtils.copy(input, os);
        } catch (Exception e) {
            throw new IllegalArgumentException("Invalid file: " + e, e);
        }

        return new CommonsMultipartFile(item);
    }

在使用上面的方法获取到相关的文件编码后,存取文件时使用此编码进行即可,如下。

        DataInputStream in = new DataInputStream(new FileInputStream(tempFile));
        InputStreamReader inputStreamReader = new InputStreamReader(in, Charset.forName(encoding));
CSVReader csvReader = new CSVReader(inputStreamReader);

注意,这里可以不使用CSVReader,使用其他的读取方法,设定文件编码也是一样的。使用上述策略可以完全解决java开发中的文件中文乱码问题。