要正确读取包含中文字符的CSV文件,需要确保文件是以UTF-8编码保存的,并且在读取文件时正确处理编码。使用 std::wifstream
并设置其字节流的编码方式可以解决乱码问题。以下是修改后的代码:
代码说明:
-
设置UTF-8编码:
- 使用
std::locale
和std::codecvt_utf8<wchar_t>
设置文件流为UTF-8编码。这确保了在读取包含中文字符的文件时,字符能够正确解码。
- 使用
-
读取CSV文件:
- 读取文件的每一行,并将其分割成键和值。
- 将键字符串转换为
long
型,并将键值对存储在g_TextCode
中。
-
错误处理:
- 在转换键字符串时,如果发生
std::invalid_argument
或std::out_of_range
异常,记录错误并继续处理下一行。
- 在转换键字符串时,如果发生
#include <unordered_map>
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <locale>
#include <codecvt>
static const std::wstring TextCodeDataName = L"code.csv";
std::unordered_map<long, std::wstring> g_TextCode;
static bool isTextInit = false;
bool Init()
{
std::wstring binpathstr{L"e:/" };
binpathstr += TextCodeDataName;
std::wifstream file(binpathstr);
if (!file.is_open()) {
std::wcerr << L"无法打开文件: " << binpathstr << std::endl;
return false;
}
// 设置文件流使用UTF-8编码
file.imbue(std::locale(file.getloc(), new std::codecvt_utf8<wchar_t>));
std::wstring line;
while (std::getline(file, line)) {
std::wstringstream linestream(line);
std::wstring keyStr, value;
if (std::getline(linestream, keyStr, L',') && std::getline(linestream, value)) {
try {
long key = std::stol(keyStr);
g_TextCode[key] = value;
}
catch (const std::invalid_argument&) {
std::wcerr << L"CSV文件中无效的键: " << keyStr << std::endl;
continue;
}
catch (const std::out_of_range&) {
std::wcerr << L"CSV文件中超出范围的键: " << keyStr << std::endl;
continue;
}
}
}
file.close();
isTextInit = true;
return isTextInit;
}
这种方法确保了从UTF-8编码的CSV文件中读取中文字符时不会出现乱码问题。如果文件已经是UTF-8编码的,这段代码应该能正确读取并处理文件内容。
添加一个辅助函数用于ANSI到宽字符(wchar_t)的转换:
std::wstring AnsiToWString(const std::string& str)
{
int len;
int slength = static_cast<int>(str.length()) + 1;
len = MultiByteToWideChar(CP_ACP, 0, str.c_str(), slength, 0, 0);
std::wstring wstr(len, L'\0');
MultiByteToWideChar(CP_ACP, 0, str.c_str(), slength, &wstr[0], len);
return wstr;
}
std::string line;
while (std::getline(file, line)) {
std::wstring wline = AnsiToWString(line);
std::wstringstream linestream(wline);
std::wstring keyStr, value;
if (std::getline(linestream, keyStr, L',') && std::getline(linestream, value)) {
try {
long key = std::stol(keyStr);
g_TextCode[key] = value;
}
catch (const std::invalid_argument&) {
std::wcerr << L"CSV文件中无效的键: " << keyStr << std::endl;
continue;
}
catch (const std::out_of_range&) {
std::wcerr << L"CSV文件中超出范围的键: " << keyStr << std::endl;
continue;
}
}
}