MultiByteToWideChar 不能很好地转换我的字符串
MultiByteToWideChar does not convert my string well
我正在 std::string
上构建一个合成的 UTF-8 字符串,并尝试用 MultiByteToWideChar
转换它。
这是我的代码:
std::string str;
str += 'A';
str += char(0);
str += 'B';
str += char(0);
str += 'C';
str += char(0);
str += char(0);
str += char(0);
std::wstring wstr;
if (str.empty()){
wstr = L"";
}
int sizeNeeded = MultiByteToWideChar(CP_UTF8, 0, str.data(), str.size(), NULL, 0) + 1;
std::wstring wstrTo(sizeNeeded, 0);
MultiByteToWideChar(CP_UTF8, 0, str.data(), str.size(), &wstrTo[0], sizeNeeded);
wstr = wstrTo;
std::wcout << wstr;
事实证明,MultiByteToWideChar
并没有将 str
简单地转换为 L"ABC" 字符串,而是将每个字符分别转换为 wchar_t
- 这意味着 'A' + char(0)
不会变成L'A'
而是变成L'A' + L'[=18=]'
我是不是做错了什么,或者这是 MultiByteToWideChar
的预期行为?
您对字符串 "ABC"
的编码不正确。空字符是虚假的。 ASCII 范围内的字符在 UTF-8 中以单个八位位组编码。
编码如下:
std::string str;
str += 'A';
str += 'B':
str += 'C';
str += 0;
虽然
std::string str = "ABC";
更简单。
std::string str;
str += 'A';
str += char(0);
str += 'B';
str += char(0);
str += 'C';
str += char(0);
str += char(0);
str += char(0);
这不是生成 UTF-8 编码的字符串!它正在生成一个 UTF-16 编码的字符串。
int sizeNeeded = MultiByteToWideChar(CP_UTF8, 0, str.data(), str.size(), NULL, 0) + 1;
您告诉 MultiByteToWideChar()
将 str
的原始字节解释为 UTF-8,即使它实际上并未以 UTF-8 编码。
Unicode 代码点 U+0000
在 UTF-8 中有效(它被编码为 0x00
),因此 str
中的每个 0x00
字符将被解释为代码点 U+0000
,其余字符将按原样解释,因为它们都小于 U+0080
。因此,在您的 "UTF-8" 字符串中没有 多字节 序列,只有 单字节 序列。
您最终得到一个包含以下代码点的 UTF-16 wstring
:
0x41 -> U+0041
0x00 -> U+0000
0x42 -> U+0042
0x00 -> U+0000
0x43 -> U+0043
0x00 -> U+0000
0x00 -> U+0000
0x00 -> U+0000
如果您将 str
正确编码为 UTF-8,然后将其解释为 UTF-8,您最终会得到正确的 UTF-16 wstring
:
std::string str;
str += 'A';
str += 'B';
str += 'C';
str += char(0);
0x41 -> U+0041
0x42 -> U+0042
0x43 -> U+0043
0x00 -> U+0000
或者,如果您将 str
编码为 UTF-16 并将其解释为 UTF-16(您不能使用 MultiByteToWideChar()
,您必须手动完成),您将仍然以包含正确代码点的 UTF-16 wstring
结束:
std::string str;
str += 'A';
str += char(0);
str += 'B';
str += char(0);
str += 'C';
str += char(0);
str += char(0);
str += char(0);
0x41 0x00 -> U+0041
0x42 0x00 -> U+0042
0x43 0x00 -> U+0043
0x00 0x00 -> U+0000
我正在 std::string
上构建一个合成的 UTF-8 字符串,并尝试用 MultiByteToWideChar
转换它。
这是我的代码:
std::string str;
str += 'A';
str += char(0);
str += 'B';
str += char(0);
str += 'C';
str += char(0);
str += char(0);
str += char(0);
std::wstring wstr;
if (str.empty()){
wstr = L"";
}
int sizeNeeded = MultiByteToWideChar(CP_UTF8, 0, str.data(), str.size(), NULL, 0) + 1;
std::wstring wstrTo(sizeNeeded, 0);
MultiByteToWideChar(CP_UTF8, 0, str.data(), str.size(), &wstrTo[0], sizeNeeded);
wstr = wstrTo;
std::wcout << wstr;
事实证明,MultiByteToWideChar
并没有将 str
简单地转换为 L"ABC" 字符串,而是将每个字符分别转换为 wchar_t
- 这意味着 'A' + char(0)
不会变成L'A'
而是变成L'A' + L'[=18=]'
我是不是做错了什么,或者这是 MultiByteToWideChar
的预期行为?
您对字符串 "ABC"
的编码不正确。空字符是虚假的。 ASCII 范围内的字符在 UTF-8 中以单个八位位组编码。
编码如下:
std::string str;
str += 'A';
str += 'B':
str += 'C';
str += 0;
虽然
std::string str = "ABC";
更简单。
std::string str;
str += 'A';
str += char(0);
str += 'B';
str += char(0);
str += 'C';
str += char(0);
str += char(0);
str += char(0);
这不是生成 UTF-8 编码的字符串!它正在生成一个 UTF-16 编码的字符串。
int sizeNeeded = MultiByteToWideChar(CP_UTF8, 0, str.data(), str.size(), NULL, 0) + 1;
您告诉 MultiByteToWideChar()
将 str
的原始字节解释为 UTF-8,即使它实际上并未以 UTF-8 编码。
Unicode 代码点 U+0000
在 UTF-8 中有效(它被编码为 0x00
),因此 str
中的每个 0x00
字符将被解释为代码点 U+0000
,其余字符将按原样解释,因为它们都小于 U+0080
。因此,在您的 "UTF-8" 字符串中没有 多字节 序列,只有 单字节 序列。
您最终得到一个包含以下代码点的 UTF-16 wstring
:
0x41 -> U+0041
0x00 -> U+0000
0x42 -> U+0042
0x00 -> U+0000
0x43 -> U+0043
0x00 -> U+0000
0x00 -> U+0000
0x00 -> U+0000
如果您将 str
正确编码为 UTF-8,然后将其解释为 UTF-8,您最终会得到正确的 UTF-16 wstring
:
std::string str;
str += 'A';
str += 'B';
str += 'C';
str += char(0);
0x41 -> U+0041
0x42 -> U+0042
0x43 -> U+0043
0x00 -> U+0000
或者,如果您将 str
编码为 UTF-16 并将其解释为 UTF-16(您不能使用 MultiByteToWideChar()
,您必须手动完成),您将仍然以包含正确代码点的 UTF-16 wstring
结束:
std::string str;
str += 'A';
str += char(0);
str += 'B';
str += char(0);
str += 'C';
str += char(0);
str += char(0);
str += char(0);
0x41 0x00 -> U+0041
0x42 0x00 -> U+0042
0x43 0x00 -> U+0043
0x00 0x00 -> U+0000