Подтвердить что ты не робот

С++ и Boost: кодирование/декодирование UTF-8

Я пытаюсь выполнить очень простую задачу: возьмите unicode-aware wstring и преобразуйте его в string, закодированный как байты UTF8, а затем наоборот: возьмите string, содержащий UTF8 байтов и преобразовать его в unicode-aware wstring.

Проблема в том, что мне нужна кросс-платформа, и мне нужно, чтобы она работала с Boost... и я просто не могу понять, как заставить ее работать. Я играл с

Попытка конвертировать код для использования stringstream/wstringstream вместо файлов любого типа, но ничего не работает.

Например, в Python это будет выглядеть так:

>>> u"שלום"
u'\u05e9\u05dc\u05d5\u05dd'
>>> u"שלום".encode("utf8")
'\xd7\xa9\xd7\x9c\xd7\x95\xd7\x9d'
>>> '\xd7\xa9\xd7\x9c\xd7\x95\xd7\x9d'.decode("utf8")
u'\u05e9\u05dc\u05d5\u05dd'

То, что я в конечном счете, это следующее:

wchar_t uchars[] = {0x5e9, 0x5dc, 0x5d5, 0x5dd, 0};
wstring ws(uchars);
string s = encode_utf8(ws); 
// s now holds "\xd7\xa9\xd7\x9c\xd7\x95\xd7\x9d"
wstring ws2 = decode_utf8(s);
// ws2 now holds {0x5e9, 0x5dc, 0x5d5, 0x5dd}

Я действительно не хочу добавлять другую зависимость от ICU или что-то в этом духе... но, насколько мне известно, это возможно с помощью Boost.

Некоторый пример кода будет очень оценен! Благодаря

4b9b3361

Ответ 1

Спасибо всем, но в конечном итоге я прибегал к http://utfcpp.sourceforge.net/ - это библиотека только для заголовков, которая очень легкая и простая в использовании. Я делюсь демо-кодом здесь, если кто-нибудь найдет его полезным:

inline void decode_utf8(const std::string& bytes, std::wstring& wstr)
{
    utf8::utf8to32(bytes.begin(), bytes.end(), std::back_inserter(wstr));
}
inline void encode_utf8(const std::wstring& wstr, std::string& bytes)
{
    utf8::utf32to8(wstr.begin(), wstr.end(), std::back_inserter(bytes));
}

Использование:

wstring ws(L"\u05e9\u05dc\u05d5\u05dd");
string s;
encode_utf8(ws, s);

Ответ 2

В комментариях уже есть ссылка boost, но в почти стандартном С++ 0x есть wstring_convert, который делает это

#include <iostream>
#include <string>
#include <locale>
#include <codecvt>
int main()
{
    wchar_t uchars[] = {0x5e9, 0x5dc, 0x5d5, 0x5dd, 0};
    std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
    std::string s = conv.to_bytes(uchars);
    std::wstring ws2 = conv.from_bytes(s);
    std::cout << std::boolalpha
              << (s == "\xd7\xa9\xd7\x9c\xd7\x95\xd7\x9d" ) << '\n'
              << (ws2 == uchars ) << '\n';
}

при компиляции с MS Visual Studio 2010 EE SP1 или с CLang++ 2.9

true 
true

Ответ 3

Boost.Locale был выпущен в Boost 1.48 (15 ноября 2011 г.), что упростило преобразование из и в UTF8/16

Вот несколько удобных примеров из документов:

string utf8_string = to_utf<char>(latin1_string,"Latin1");
wstring wide_string = to_utf<wchar_t>(latin1_string,"Latin1");
string latin1_string = from_utf(wide_string,"Latin1");
string utf8_string2 = utf_to_utf<char>(wide_string);

Почти так же просто, как кодирование/декодирование Python:)

Обратите внимание, что Boost.Locale не является библиотекой только для заголовков.

Ответ 4

Для замены замены для std::string/std::wstring, который обрабатывает utf8, см. tinyutf8.

В сочетании с <codecvt> вы можете конвертировать большую часть из/в каждую кодировку из/в utf8, которую вы затем обрабатываете через над библиотекой.