要正确读取包含中文字符的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;}}}