Почему некоторые широкие строки в кодировке utf16 при преобразовании в узкие строки в кодировке utf8 преобразуются в шестнадцатеричные значения, которые кажутся неправильными при преобразовании с помощью этой широко распространенной функции преобразования?
std::string convert_string(const std::wstring& str)
{
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
return conv.to_bytes(str);
}
Привет. У меня есть приложение C ++ в Windows, которое принимает пользовательский ввод в командной строке. Я использую основную точку входа с широкими символами, чтобы получить ввод в виде строки utf16, которую я конвертирую в узкую строку utf8 с помощью вышеуказанной функции.
Эта функция может быть найдена во многих местах в Интернете и работаетпочти во всех случаях. Однако я нашел несколько примеров, где он не работает должным образом.
Например, если я ввожу символ emojii "?" в виде строкового литерала (в моем cpp-файле с кодировкой utf8) и напишу егона диск, файл (FILE-1) содержит следующие данные (которые являются правильными шестнадцатеричными значениями utf8, указанными здесь https://www.fileformat.info/info/unicode/char/1f922/index.htm):
0xF0 0x9F 0xA4 0xA2
Однако, если я передам emojii моему приложению в командной строке ипреобразовать его в строку utf8 с помощью функции преобразования, описанной выше, а затем записать ее на диск, файл (FILE-2) содержит различные необработанные байты:
0xED 0xA0 0xBE 0xED 0xB4 0xA2
В то время как второй файл, кажется, указывает на то, что преобразование произвелонеправильный вывод, если вы копируете и вставляете шестнадцатеричные значения (по крайней мере, в notepad ++), это приводит к правильному смайлику. Также WinMerge считает, что два файла идентичны.
, поэтому в заключение я хотел бы знать следующее:
- как некорректно выглядящие преобразованные шестнадцатеричные значения правильно отображаются на правильный символ utf8 в примере выше
- почему функция преобразования преобразует некоторые символы в эту форму, в то время как почти все другие символы выдают ожидаемые необработанные байты
- В качестве бонуса я хотел бы знать, возможно ли изменить функцию преобразования для остановкипри выводе этих редких символов в этой форме
Я должен отметить, что у меня уже есть обходная функция, которая использует вызовы 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;
}