如何遍历wstring中的实际Unicode字符?wstring存储疑问
问题分析与解决
为什么wstring长度是5且存储的是字节?
你的问题核心在于wifstream默认没有做编码转换。当你直接用wifstream读取UTF-8编码的文件时,它使用系统默认的窄字符locale,不会将文件中的UTF-8字节转换为宽字符(你的环境中wchar_t是2字节,对应UTF-16编码)。
实际发生的是:文件里的每个UTF-8字节被直接存入wchar_t的低8位,高位补0。比如字符串"Hálo"的UTF-8编码是0x48 0xC3 0xA1 0x6C 0x6F(共5字节),所以wstring的长度是5,每个元素分别是这5个字节的数值(72、195、161、108、111),看起来就像把char数组塞进了wstring。
至于写入文件时能正确显示,是因为wofstream同样用默认locale,把wstring中每个wchar_t的低8位直接写入文件,相当于又还原了原始的UTF-8字节,所以文件内容正常。
如何正确遍历wstring中的实际Unicode字符?
要让wifstream正确解析UTF-8并转换为宽字符,需要给它设置支持UTF-8转换的locale。具体步骤如下:
- 包含必要的头文件:
<locale>和<codecvt> - 在打开文件后,为
wifstream设置UTF-8转宽字符的locale
修改后的示例代码:
#include <iostream> #include <fstream> #include <string> #include <locale> #include <codecvt> int main() { std::wifstream inFile; // 设置locale,将UTF-8转换为wchar_t(UTF-16) inFile.imbue(std::locale(std::locale(), new std::codecvt_utf8<wchar_t>)); inFile.open(L"myFile.txt"); std::wstring str; std::getline(inFile, str); std::wcout << str.length() << std::endl; for (unsigned int i = 0; i < str.length(); i++) { // 打印字符的Unicode代码点整数值 std::wcout << str[i] << L" (" << static_cast<unsigned int>(str[i]) << L')' << std::endl; } std::wofstream outFile; // 同样给输出流设置locale,确保写入时转换为UTF-8 outFile.imbue(std::locale(std::locale(), new std::codecvt_utf8<wchar_t>)); outFile.open(L"outFile.txt"); outFile << str << std::endl; outFile.close(); inFile.close(); return 0; }
修改后,str.length()会返回4(对应4个Unicode字符),遍历每个str[i]得到的是:
- H (72)
- á (225) (0xE1,á的Unicode代码点)
- l (108)
- o (111)
这样你就能正确遍历每个实际的Unicode字符,并且打印它们的代码点整数值。
内容的提问来源于stack exchange,提问作者James P
相关产品推荐
相关产品推荐

