csv日文乱码问题的解决

解决日文中文导出CSV文件乱码问题

常见编码和编码头BOM:https://www.cnblogs.com/signheart/p/c3b1000186199e89d4e02c33f39ed418.html

乱码问题很头疼,日文的乱码问题更是头疼。按照常理来讲日本人较真工匠精神那么按理来说搜索工具类对应的日文应用问题应该能很好的搜索出来问题的解决方案。但是结果让人惊讶,日文应用乱码的问题搜索结果出来最多的是英文和中文,最后才是日文。打开日文的文章一看,大跌眼镜,简简单单的把最基础的测试用例一COPY算是完事了,完全对不起他们的民族精神。再回过头来说问题,日文导出CSV有两个问题需要解决:

  1. 日文、中文乱码;
  2. 逗号分隔符失效了,所有内容都在一行;
  • 对于上述两个问题都归咎于字符集的问题。解决好了字符集的问题,以上的问题迎刃而解。另外一个问题则是引入UTF-8时候BOM的问题。好在这里顺带补一下BOM的知识。
  • BOM(英语:byte-order mark)字节顺序标记:是位于码点U+FEFF的统一码字符的名称。当以UTF-16或UTF-32来将UCS/统一码字符所组成的字符串编码时,这个字符被用来标示其字节序。它常被用来当做标示文件是以UTF-8、UTF-16或UTF-32编码的记号。BOM也是Unicode标准的一部分,有它特定的适用范围。通常BOM是用来标示Unicode纯文本字节流的,用来提供一种方便的方法让文本处理程序识别读入的.txt文件是哪个Unicode编码(UTF-8,UTF-16BE,UTF-16LE)。Windows相对对BOM处理比较好,是因为Windows把Unicode识别代码集成进了API里,主要是CreateFile()。打开文本文件时它会自动识别并剔除BOM。Windows用这个有历史原因,因为它最初脱胎于多代码页的环境。而引入Unicode时Windows的设计者又希望能在用户不注意的情况下同时兼容Unicode和非Unicode(Multiple byte)文本文件,就只能借助这种小trick了。相比之下,Linux这样的系统在多locale的环境中浸染的时间比较短,再加上社区本身也有足够的动力轻装前进(吐槽:微软对兼容性的要求确实是到了非常偏执的地步,任何一点破坏兼容性的做法都不允许,以至于很多时候是自己绑住自己的双手),所以干脆一步到位进入UTF-8。

具体的实现咱们看下代码:

package com.yneit.test;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;

import org.springframework.util.NumberUtils;
import org.supercsv.cellprocessor.FmtBool;
import org.supercsv.cellprocessor.FmtDate;
import org.supercsv.cellprocessor.constraint.LMinMax;
import org.supercsv.cellprocessor.constraint.NotNull;
import org.supercsv.cellprocessor.constraint.UniqueHashCode;
import org.supercsv.cellprocessor.ift.CellProcessor;
import org.supercsv.io.CsvListWriter;
import org.supercsv.io.ICsvListWriter;
import org.supercsv.prefs.CsvPreference;

import au.com.bytecode.opencsv.CSVWriter;

/**
 * CSV 日文乱码解决
 */
public class Test {

    // 日文字使用符集
    public static String UTF_16LE = "UTF-16LE";
    public static String UTF_8 = "UTF-8";

    public static void main(String[] args) throws IOException {
        String path = "G:\\Project_Java\\MyProject\\src\\com\\yneit\\work\\test.csv";
        String encoder = UTF_8;

        OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(path), encoder);
        out.write(0xFEFF);
        CSVWriter writer = new CSVWriter(out, CSVWriter.DEFAULT_SEPARATOR,
                CSVWriter.NO_QUOTE_CHARACTER, CSVWriter.NO_ESCAPE_CHARACTER,
                CSVWriter.DEFAULT_LINE_END);

        String[] entries = { "1", "fir", "リージョン", "6", "人民", "ond,政府\"ird" };
        String[] datas = new String[entries.length];
        for (int i = 0; i < entries.length; i++) {
            String item = Test.verityCell(entries[i]);
            datas[i] = item;
        }

        writer.writeNext(datas);
        writer.close();

        System.out.println("over");

        try {
            Test.writeWithCsvListWriter();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * @return the cell processors
     */
    private static CellProcessor[] getProcessors() {

        final CellProcessor[] processors = new CellProcessor[] { new UniqueHashCode(), // customerNo
                                                                                        // (must
                                                                                        // be
                                                                                        // unique)
                new NotNull(), // firstName
                new NotNull(), // lastName
                new FmtDate("dd/MM/yyyy"), // birthDate
                new NotNull(), // mailingAddress
                new Optional(new FmtBool("Y", "N")), // married
                new Optional(), // numberOfKids
                new NotNull(), // favouriteQuote
                new NotNull(), // email
                new LMinMax(0L, LMinMax.MAX_LONG) // loyaltyPoints
        };

        return processors;
    }

    /**
     * An example of reading using CsvListWriter.
     */
    private static void writeWithCsvListWriter() throws Exception {

        // create the customer Lists (CsvListWriter also accepts arrays!)
        final List<Object> john = Arrays.asList(new Object[] { "1", "リージョン", "リー",
                new GregorianCalendar(1945, Calendar.JUNE, 13).getTime(),
                "1600 リー Parkway\nz中国现实 View, CA 94043\nUnited States", null, null,
                "\"May the Force リー with you.\" - Star Wars", "jdunbar@gmail.com", 0L });

        final List<Object> bob = Arrays.asList(new Object[] { "2", "Bob", "Down",
                new GregorianCalendar(1919, Calendar.FEBRUARY, 25).getTime(),
                "1601 Willow Rd.\nリー Park, CA 94025\nUnited States", true, 0,
                "\"Frankly, my dear, I don't give a damn.\" - Gone With The Wind", "天朝@hotmail.com",
                123456L });

        ICsvListWriter listWriter = null;
        try {
            OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(
                    "G:\\Project_Java\\MyProject\\src\\com\\yneit\\work\\writeWithCsvListWriter.csv"),
                    Charset.forName(UTF_8));
            out.write('\uFEFF');
            listWriter = new CsvListWriter(out, CsvPreference.STANDARD_PREFERENCE);

            final CellProcessor[] processors = Test.getProcessors();
            final String[] header = new String[] { "customerNo", "firstName", "lastName",
                    "birthDate", "mailingAddress", "married", "numberOfKids", "favouriteQuote",
                    "email", "loyaltyPoints" };

            // write the header
            listWriter.writeHeader(header);

            // write the customer lists
            listWriter.write(john, processors);
            listWriter.write(bob, processors);

        }
        finally {
            if (listWriter != null) {
                listWriter.close();
            }
        }
    }

    public static String verityCell(String content) {
        if (content == null) {
            return "";
        }

        if (NumberUtils.isNumber(content) && content.length() > 0) {
            content = "\t" + content;
        }

        if (content.indexOf(CSVWriter.DEFAULT_QUOTE_CHARACTER) > -1
                || content.indexOf(CSVWriter.DEFAULT_SEPARATOR) > -1) {
            content = StringUtils.replace(content,
                    String.valueOf(CSVWriter.DEFAULT_QUOTE_CHARACTER),
                    "" + CSVWriter.DEFAULT_QUOTE_CHARACTER + CSVWriter.DEFAULT_QUOTE_CHARACTER);
            content = CSVWriter.DEFAULT_QUOTE_CHARACTER + content
                    + CSVWriter.DEFAULT_QUOTE_CHARACTER;
        }
        else {
            content = CSVWriter.DEFAULT_QUOTE_CHARACTER + content
                    + CSVWriter.DEFAULT_QUOTE_CHARACTER;
        }
        return content;
    }
}

 

### Linux 下 CSV 文件编码问题解决方案 在 Linux 环境下处理 CSV 文件时,可能会遇到因字符编码不同而导致的乱码问题。以下是针对此问题的具体分析和解决方案。 #### 1. **确认文件的实际编码** 在解决问题之前,需先确认原始 CSV 文件的真实编码格式。可以使用 `file` 命令或者 Python 的第三方库 `chardet` 来检测文件编码: ```bash file -i your_file.csv ``` 上述命令会返回文件的 MIME 类型及其编码信息。如果需要更精确的结果,可借助 Python 脚本实现自动检测: ```python import chardet with open('your_file.csv', 'rb') as f: raw_data = f.read() result = chardet.detect(raw_data) print(result['encoding']) ``` 以上方法可以帮助快速定位文件实际使用的编码[^1]。 #### 2. **转换文件编码至 UTF-8** 当发现文件并非以 UTF-8 编码存储时,可以通过工具将其转换为目标编码(即 UTF-8)。推荐的方法如下: ##### 使用 iconv 工具 iconv 是一种强大的字符编码转换工具,在大多数 Linux 发行版中预装。其基本语法为: ```bash iconv -f original_encoding -t utf-8 input_file.csv -o output_file.csv ``` 例如,假设原文件是以 GBK 或 Shift_JIS 编码保存,则运行以下命令即可完成转换: ```bash iconv -f gbk -t utf-8 input_file.csv -o output_file_utf8.csv ``` 或对于日文环境下的 Shift-JIS 编码文件: ```bash iconv -f shift_jis -t utf-8 input_file.csv -o output_file_utf8.csv ``` 此处 `-f` 参数表示源文件的当前编码,而 `-t` 则定义目标编码。 #### 3. **Python 中读取并写入正确编码CSV 文件** 即使已经完成了文件的整体编码转换,但在某些情况下仍可能需要动态调整数据流中的编码设置。此时可通过 Python 实现更加灵活的操作流程。下面是一个简单的例子展示如何安全地加载非标准编码的数据到 Pandas DataFrame 并重新导出为 UTF-8 格式的 CSV 文件: ```python import pandas as pd # 加载带有特定编码CSV 数据 df = pd.read_csv('input_file.csv', encoding='shift_jis') # 将 DataFrame 导出回新的 CSV 文件,并指定输出编码为 UTF-8 df.to_csv('output_file_utf8.csv', index=False, encoding='utf-8') ``` 注意这里的关键在于调用了 `pd.read_csv()` 函数的同时设置了合适的参数来匹配输入文件原有的编码形式;同样地,在写出阶段也明确了期望的目标编码类型[^2]。 另外需要注意的是,如果字符串本身包含了多种混合编码的内容,则单纯依靠整体层面的统一重设未必能够完全消除潜在隐患。因此建议尽可能保持整个项目生命周期内的单一标准化编码实践——优先考虑 UTF-8 作为首选方案[^3]。 --- #### 总结 综上所述,解决 Linux 系统上的 CSV 文件乱码问题主要涉及以下几个方面的工作:一是准确判断现有文档的确切编码属性;二是运用适当的技术手段实施必要的编码迁移操作;三是利用编程语言内置功能进一步优化后续加工环节里的兼容性表现。只要遵循这些原则,就能有效规避绝大多数常见的跨平台文本交换障碍现象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值