С++ и 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.
Некоторый пример кода будет очень оценен! Благодаря
Ответы
Ответ 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, которую вы затем обрабатываете через над библиотекой.