windows-1252不是utf-8,直接用std::string读取并当作utf-8处理会导致乱码或解析失败;必须显式转码,windows平台推荐multibytetowidechar,跨平台推荐iconv。

Windows-1252不是UTF-8,std::string本身不携带编码信息
直接用std::string读取Windows-1252字节流,再当成UTF-8处理(比如传给Qt、WinAPI宽字符函数或JSON库),大概率出现乱码或解析失败。C++标准库不内置代码页转换,必须显式转码——这是最常被忽略的前提。
用MultiByteToWideChar转到wchar_t(Windows平台首选)
Windows原生支持Windows-1252,MultiByteToWideChar是最快最稳的方式,无需第三方依赖:
std::wstring to_wstring_win1252(const std::string& s) {
if (s.empty()) return {};
int len = MultiByteToWideChar(1252, 0, s.c_str(), -1, nullptr, 0);
if (len == 0) return {};
std::wstring result(len - 1, L'\0');
MultiByteToWideChar(1252, 0, s.c_str(), -1, &result[0], len);
return result;
}
-
1252是Windows-1252的代码页ID,不能写成CP1252(那是宏,需#include <windows.h></windows.h>) - 第二个参数为
0表示不校验非法字节;若需严格校验,改用MB_ERR_INVALID_CHARS,但会返回0并设GetLastError()为ERROR_NO_UNICODE_TRANSLATION - 传
-1让API自动包含末尾\0,所以结果长度要减1
跨平台方案:用iconv或std::codecvt(已弃用,慎用)
std::codecvt_utf8<wchar_t></wchar_t>只支持UTF-8↔UTF-16/32,不支持Windows-1252;C++17起std::codecvt已被弃用。可靠跨平台做法是引入iconv:
// 需链接 -liconv
iconv_t cd = iconv_open("UTF-8", "WINDOWS-1252");
size_t in_left = s.size(), out_left = buf_size;
char* in_buf = const_cast<char>(s.data());
char* out_buf = output_buffer;
iconv(cd, &in_buf, &in_left, &out_buf, &out_left);
iconv_close(cd);</char>
-
iconv的编码名必须用"WINDOWS-1252"(全大写+连字符),不是"cp1252"或"win1252" - Linux/macOS默认带
libiconv,Windows需手动编译或用MSYS2/Conan安装 - 部分旧版
iconv不支持WINDOWS-1252别名,可试"CP1252"(非标准但常见)
用std::from_chars或std::stoi解析数字?别碰Windows-1252里的数字
Windows-1252中数字'0'–'9'和ASCII一致,但如果你从文件读出的是含Windows-1252编码的整个字符串(比如CSV含重音字符),而只拿其中某段当数字解析,std::stoi仍能工作——因为数字字节没变。但以下情况会崩:
- 字符串里混有Windows-1252特有字符(如
’U+2019,字节0x92),被误当控制符截断 - 用
std::string::find按ASCII标点切分,但分隔符在Windows-1252里是不同字节(如é占1字节0xE9,不是UTF-8的2字节) - 把整段Windows-1252数据直接喂给
nlohmann::json::parse,它默认按UTF-8解码,必然报parse_error.101
真正麻烦的从来不是“怎么转”,而是“在哪转、转几次、谁负责清理残留字节”。一旦路径里混入未转码的Windows-1252字节,后续所有文本操作都可能静默错位。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











