我正在从包含 unicode 字符的文件中读取文本,并将文本存储到
wstring
中。我有兴趣迭代 wstring
以确定哪些字符需要多个字节来存储。
我的问题是
str.length()
(其中 str
是 wstring
)似乎指示字符串中的字节数而不是字符数。另外,当我使用 str[i]
迭代字符串时,括号运算符似乎仅返回 1 个字节。
这是一些复制我的问题的示例代码:
wifstream inFile;
inFile.open(L"myFile.txt");
wstring str;
getline(inFile, str);
wcout << str.length() << endl;
for (unsigned int i = 0; i < str.length(); i++) {
wcout << str[i] << L" (" << (unsigned int)str[i] << L')' << endl;
}
wofstream outFile; outFile.open(L"outFile.txt");
outFile << str << endl;
outFile.close();
inFile.close();
代码输出:
5
H (72)
├ (195)
í (161)
l (108)
o (111)
我尝试使用包含字符串
"Hálo"
的文件。 str.length()
报告 5,这似乎是存储字符串所需的最小字节数(假设您对除 á 之外的所有字符使用一个字节)。这让我很困惑,因为在我的环境中 sizeof(wchar_t)
是 2。我认为 wstring 中的 4 个字符数组至少需要 8 个字节。然而,似乎"Hálo"
被存储为01001000 {11000011 10100001} 01101100 01101100
(大括号表示unicode字符)。因此,当我迭代此操作时,我得到的所有内容都返回了,就好像它们只是 char
并且 unicode 字符 á
返回为 2 个字符 ├í
。
奇怪的是,当我将 wstring 写入文件时(在上面的代码中看到),文本按预期显示,并且正确解释了 unicode 字符。
有没有办法迭代
wstring
中的实际字符而不仅仅是字节?另外,为什么 wstring
将其存储在 5 个字节而不是 8 个字节中?我认为它节省了空间,但它使访问元素看起来不直观。
编辑:我知道我的终端可能无法正确显示
wchar_t
,尽管我仍然希望打印它的整数值。
您所说的关于
std::wstring
的一切都是不正确的。它不存储 bytes,并且它的 length()
不以 bytes 表示(这些对于 std::string
来说是正确的)。
std::wstring
保存 wchar_t
个字符,其 length()
是字符串中 wchar_t
元素的数量。根据定义,sizeof(wchar_t) > sizeof(char)
,在 Windows 上 wchar_t
为 2 个字节(用于 UCS-2/UTF-16),而在其他平台上 wchar_t
为 4 个字节(用于 UTF-32)。
要使用
std::wstring
将文件读入 std::wifstream
,您需要将正确的 imbue()
放入 std::locale
来处理文件的编码(ANSI、UTF-8 等),以便可以对其进行解码变成 std::wifstream
个字符。在您的情况下,您的文件以 UTF-8 编码,因为 wchar_t
的 UTF-8 编码形式是字节序列:
Hálo
由于您的
H - 0x48
á - 0xC3 0xA1
l - 0x6C
o - 0x6F
不知道数据是 UTF-8,因此它只是将每个字节按原样升级为
std::wifstream
。您需要将 UTF-8 语言环境添加到流中才能读取此文件,以便字节 wchar_t
正确解释为 imbue()
而不是 0xC3 0xA1
。