2016-05-29 3 views
3

C++ 11 имеет инструменты для преобразования строк широких полукокса std::wstring из/в представлении utf8: std::codecvt, std::codecvt_utf8, std::codecvt_utf8_utf16 и т.д.Преобразование C++ станд :: wstring в utf8 с станд :: codecvt_xxx

Какой пригодна для использования Приложение Windows для преобразования обычных строк с широким символом Windows std::wstring в utf8 std::string? Всегда ли работает без настройки локалей?

+1

Возможный дубликат [Преобразовать wstring в строку, закодированную в UTF-8] (http://stackoverflow.com/questions/4358870/convert-wstring-to-string-encoded-in-utf-8) – IInspectable

+0

@IInsp ectable Я разместил этот вопрос после прочтения страницы, которую вы упомянули))) Я не вижу ясного ответа на свой вопрос на этой странице. –

+1

Неужели [это] (http://stackoverflow.com/a/12903901/1889329) не отвечает на ваши вопросы вопрос? Согласно [комментарий] (http://stackoverflow.com/questions/4358870/convert-wstring-to-string-encoded-in-utf-8#comment32601904_12903901) * «[t] его работы для Windows, если вы используете VS2012 или позже"*. – IInspectable

ответ

1

Похоже, что std::codecvt_utf8 хорошо подходит для преобразования std::wstring ->utf8. Он прошел все мои тесты. (Приложение Windows, Visual Studio 2015, Windows 8 с локалием EN)

Мне нужен способ конвертировать имена файлов в UTF8. Поэтому мой тест касается имен файлов.

В моем приложении я использую boost::filesystem::path 1.60.0 для обработки пути к файлу. Он работает хорошо, но не способен правильно преобразовывать имена файлов в UTF8. Внутренняя версия Windows boost::filesystem::path использует std::wstring для хранения пути к файлу. К сожалению, встроенное преобразование в std::string работает плохо.

Тестовый пример:

  • создать файл со смешанными символами c:\test\皀皁皂皃的 (некоторые случайные азиатские символы)
  • реж сканирования с boost::filesystem::directory_iterator, получить boost::filesystem::path файла
  • преобразовать его в std::string через встроенные конверсия filenamePath.string()
  • вы получаете c:\test\?????. Азиатские символы преобразуются в '?'. Нехорошо.

boost::filesystem использует std::codecvt внутренне. Он не работает для преобразования std::wstring ->std::string.

Вместо возведения в boost::filesystem::path преобразования можно определить функцию преобразования, как это (original snippet):

std::string utf8_to_wstring(const std::wstring & str) 
{ 
    std::wstring_convert<std::codecvt_utf8<wchar_t>> myconv; 
    return myconv.to_bytes(str); 
} 

Затем вы можете конвертировать FilePath в UTF8 легко: utf8_to_wstring(filenamePath.wstring()). Он работает отлично.

Он работает для любого пути к файлу. Я тестировал строки ASCII c:\test\test_file, азиатские строки c:\test\皀皁皂皃的, русские строки c:\test\абвгд, смешанные струны c:\test\test_皀皁皂皃的, c:\test\test_абвгд, c:\test\test_皀皁皂皃的_абвгд. Для каждой строки я получаю действительное представление UTF8.

4

Зависит от способа их преобразования.
Необходимо указать тип исходного кода и тип целевого кодирования.
wstring не является форматом, он просто определяет тип данных.

Сейчас, как правило, когда один говорит «Unicode», один означает UTF16 что и Microsoft Windows использует, и это то, что usuasly wstring содержит.

Таким образом, правильный способ преобразования из UTF8 в UTF16:

 std::string utf8String = "blah blah"; 

    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> convert; 
    std::wstring utf16String = convert.from_bytes(utf8String); 

И наоборот:

 std::wstring utf16String = "blah blah"; 

    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> convert; 
    std::string utf8String = convert.to_bytes(utf16String); 

И добавить к путанице:
При использовании std::string на a windows платформа (например, при использовании многобайтовой компиляции), это НЕ UTF8. Они используют ANSI.
Более конкретно, язык кодирования по умолчанию, используемый вашими окнами.

Также обратите внимание, что wstring is not exactly the same as UTF-16.

При компиляции в Unicode команды Windows API ожидать, что эти форматы:

Команда - многобайтовую - ANSI
Команда W - Unicode - UTF16

+0

* «Обычно, когда говорят« Юникод », один означает UTF16« * - Uhm ... Когда говорят «Юникод», я надеюсь, что кто-то знает Unicode и не путает стандарт с произвольной кодировкой. * «Когда вы используете std :: string на платформе Windows [...], это НЕ UTF8, они используют ANSI.» * - Кодировка символов, используемая для 'std :: string', определяется реализацией (то есть компилятором) , а не целевой платформы. Вы можете написать компилятор, который использует кодировку UTF-8 для 'std :: string' в Windows. – IInspectable