C++导出CSV文件时中韩文乱码 如何无需额外操作正常查看?
CSV导出中韩文乱码修复方案
问题背景
已实现英文文本CSV文件导出及本地化功能,拉丁字母类语言(如德语)的内容均可正常显示,但程序无法正常导出中韩文到CSV,会显示乱码,效果如下:
正常英文版本显示效果如下:
尝试按照UTF-8编码方案处理导出的CSV文件后,显示效果如下:
目前可正常导出和导入含中文的CSV文件,无运行报错,需求是导出的CSV无需任何额外操作即可直接正常显示中韩文内容。
现有代码
导出逻辑
ofstream file(filename); // file.imbue(locale(file.getloc(), new std::codecvt_utf16<wchar_t, 0x10ffff, std::little_endian>())); file << outputListWaveform << "\n"; //this is the part get the header of each column for (int x = 0; x < data.size(); ++x) { file << get<0>(data.at(x)); if (x != data.size() - 1) file << ","; } file << "\n"; for (int i = 0; i < get<1>(data.at(0)).size(); ++i) { for (int j = 0; j < data.size(); ++j) { auto header = get<0>(data.at(j)); auto dVal = get<1>(data.at(j)); auto bVal = get<2>(data.at(j)); file << ((header == FileOpConstants::BOST || header == FileOpConstants::EOST) ? bVal.at(i) : dVal.at(i)); if (j != data.size() - 1) file << ","; } file << "\n"; } file.close();
导入逻辑
StepTable data; ifstream file(filename); if (!file.is_open()) { string errMsg = "Could not open file: " + filename; throw runtime_error(errMsg); } string line, colname; if (file.good()) { getline(file, line); // metadata (e.g. "Output List Waveform" as generated using Cyclops) getline(file, line); // column header stringstream ss(line); while (getline(ss, colname, ',')) { data.push_back({colname, vector<double>{}, vector<bool>{}}); } } // Get Column Values (row by row) while (getline(file, line)) { int i = 0; auto val = Utility::split(line, ','); for (const auto& v : val) { auto header = get<0>(data.at(i)); if (header == FileOpConstants::BOST || header == FileOpConstants::EOST) { get<2>(data.at(i)).push_back(stoi(v)); } else if(header == VoltageHeader || header == CurrentHeader || header == PowerHeader || header == ResistanceHeader || header == TimeHeader ) { get<1>(data.at(i)).push_back(stod(v)); } else{ return {}; } i++; } } file.close(); return data;
修复方案
乱码的核心原因是Windows平台下Excel默认采用ANSI编码读取CSV文件,如果你输出的是UTF-8编码内容不带BOM头,就会出现识别错误。推荐采用以下两种方案修复:
方案1:UTF-8带BOM(兼容性最优)
该方案修改量最小,跨平台适配性好,修改导出逻辑即可:
- 打开文件后优先写入3字节的UTF-8 BOM头
\xEF\xBB\xBF - 确保所有写入的字符串本身为UTF-8编码(MSVC环境可添加编译选项
/utf-8保证源码字符串编码正确)
修改后的导出代码示例:
// 以二进制模式打开避免换行符被转义 ofstream file(filename, ios::binary); // 写入UTF-8 BOM头 file << "\xEF\xBB\xBF"; // 后续原有写入逻辑完全不变 file << outputListWaveform << "\n"; // ... 剩余原有代码保持不变
导入逻辑无需修改,若需兼容无BOM的UTF-8文件,可在读取首行时判断前3字节是否为BOM,若是则跳过即可。
方案2:UTF-16 LE带BOM(Windows原生适配)
该方案在Windows平台下完全不会出现乱码,适合仅面向Windows用户的场景:
- 改用宽字符流
wofstream写入文件 - 先写入2字节的UTF-16 LE BOM头
\xFF\xFE - 启用你之前注释的
imbue编码转换配置 - 所有写入内容转换为宽字符串格式
修改后的导出代码示例:
wofstream file(filename, ios::binary); // 写入UTF-16 LE BOM file << L"\xFF\xFE"; file.imbue(locale(file.getloc(), new std::codecvt_utf16<wchar_t, 0x10ffff, std::little_endian>())); // 后续所有写入内容需替换为wstring类型,例如: file << w_outputListWaveform << L"\n"; // ... 其余写入逻辑对应调整为宽字符输出即可
导入逻辑需要对应改为宽字符流读取,适配宽字符串处理。
内容的提问来源于stack exchange,提问作者Newbie
相关产品推荐
相关产品推荐

