aat*_*two 1 c++ string unicode utf-8 character-encoding
为什么使用utf16编码的宽字符串转换为utf8编码的窄字符串时,会转换为使用此常见转换函数转换时似乎不正确的十六进制值?
std::string convert_string(const std::wstring& str)
{
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
return conv.to_bytes(str);
}
Run Code Online (Sandbox Code Playgroud)
你好。我在Windows上有一个C ++应用,该应用在命令行上需要一些用户输入。我正在使用宽字符主入口点来获取输入为utf16字符串,并使用上述函数将其转换为utf8窄字符串。
该功能可以在网上的许多地方找到,并且几乎可以在所有情况下使用。但是,我发现了一些无法正常运行的示例。
例如,如果我输入emojii字符“”作为字符串文字(在我的utf8编码的cpp文件中)并将其写入磁盘,则文件(FILE-1)包含以下数据(这是此处指定的正确utf8十六进制值)https ://www.fileformat.info/info/unicode/char/1f922/index.htm):
0xF0 0x9F 0xA4 0xA2
Run Code Online (Sandbox Code Playgroud)
但是,如果我在命令行上将emojii传递给我的应用程序,并使用上面的转换函数将其转换为utf8字符串,然后将其写入磁盘,则文件(FILE-2)包含不同的原始字节:
0xED 0xA0 0xBE 0xED 0xB4 0xA2
Run Code Online (Sandbox Code Playgroud)
尽管第二个文件似乎表明如果您复制并粘贴十六进制值(至少在notepad ++中),则转换产生了错误的输出,但它产生了正确的emojii。WinMerge还将两个文件视为相同。
最后我很想知道以下几点:
我应该注意,我下面已经有一个变通方法,该函数使用WinAPI调用,但是仅使用标准库调用才是梦想:)
std::string convert_string(const std::wstring& wstr)
{
if(wstr.empty())
return std::string();
int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL);
std::string strTo(size_needed, 0);
WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0], size_needed, NULL, NULL);
return strTo;
}
Run Code Online (Sandbox Code Playgroud)
问题是std::wstring_convert<std::codecvt_utf8<wchar_t>>从UCS-2转换,而不是从UTF-16转换。BMP内部的字符(U + 0000..U + FFFF)在UCS-2和UTF-16中具有相同的编码,因此可以使用,但是BMP外部的字符(U + FFFF..U + 10FFFF),例如作为您的表情符号,UCS-2中根本不存在。这意味着转换无法理解该字符,并且会产生不正确的UTF-8字节(从技术上讲,它已将UTF-16代理对的每半转换为单独的UTF-8字符)。
您需要std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>改用。
| 归档时间: |
|
| 查看次数: |
61 次 |
| 最近记录: |