Кодировать / декодировать std :: string в UTF-16

Мне нужно обрабатывать формат файла (как чтение, так и запись в него), в котором строки закодированы в UTF-16 (2 байта на символ). Поскольку символы из таблицы ASCII редко используются в домене приложения, все строки в моих классах модели C ++ хранятся в экземплярах std :: string (в кодировке UTF-8).

Я ищу библиотеку (безуспешно искал в STL и Boost) или набор функций C / C ++ для обработки этого преобразования std :: string ‹-> UTF-16 при загрузке или сохранении в формат файла (фактически смоделированный как байтовый поток), включая генерацию / распознавание суррогатных пар и все эти вещи Unicode (по общему признанию, я не эксперт) ...

Какие-либо предложения? Спасибо!

РЕДАКТИРОВАТЬ: забыл упомянуть, что он должен быть кроссплатформенным (Win / Mac) и не может использовать C ++ 11.


person Peter    schedule 18.06.2012    source источник
comment
Ах, я заглянул в отделение интенсивной терапии, но оно кажется слишком большим для моей задачи.   -  person Peter    schedule 18.06.2012
comment
Если вы только ориентируетесь на окна, используйте WideCharToMultiByte, во всех остальных случаях используйте ICU. . Это можно сделать самому, но нельзя.   -  person Mooing Duck    schedule 18.06.2012
comment
Об этом спрашивали много раз, из которых я больше всего знаком: stackoverflow.com/questions/148403/   -  person Mark Ransom    schedule 18.06.2012
comment
Привет, boost есть итераторы юникода!   -  person Mooing Duck    schedule 18.06.2012


Ответы (3)


C ++ 11 имеет следующие функции:

std::string s = u8"Hello, World!";

// #include <codecvt>
std::wstring_convert<std::codecvt<char16_t,char,std::mbstate_t>,char16_t> convert;

std::u16string u16 = convert.from_bytes(s);
std::string u8 = convert.to_bytes(u16);

Однако, насколько мне известно, единственная реализация, которая пока имеет это, - это libc ++. В C ++ 11 также есть std::codecvt_utf8_utf16<char16_t>, который есть в некоторых других реализациях. В частности, codecvt_utf8_utf16 работает в VS 2010 и более поздних версиях, и поскольку wchar_t используется Windows для представления UTF-16, вы можете использовать его для преобразования между UTF -8 и собственная кодировка Windows.


Специализация codecvt<char16_t, char, mbstate_t> преобразует схемы кодирования UTF-16 и UTF-8, а специализация codecvt<char32_t, char, mbstate_t> преобразует схемы кодирования UTF-32 и UTF-8.

- [locale.codecvt] 22.4.1.4/3


Да, и у специализаций std :: codecvt есть защищенные деструкторы, а wstring_convert требует доступа к деструктору, поэтому вам действительно нужен адаптер:

template <class Facet>
class usable_facet : public Facet {
public:
    using Facet::Facet; // inherit constructors
    ~usable_facet() {}

    // workaround for compilers without inheriting constructors:
    // template <class ...Args> usable_facet(Args&& ...args) : Facet(std::forward<Args>(args)...) {}
};

template<typename internT, typename externT, typename stateT> 
using codecvt = usable_facet<std::codecvt<internT, externT, stateT>>;

std::wstring_convert<codecvt<char16_t,char,std::mbstate_t>> convert;
person bames53    schedule 18.06.2012
comment
Эй, что !? +1 Никогда такого не видел :) - person Felix Dombek; 18.06.2012
comment
Хм, сделал тестовый пример для проверки расширенных символов плоскости, но IDEOne не скомпилирует его: ideone.com/UdZcL - person Mooing Duck; 18.06.2012
comment
@MooingDuck, к сожалению, в libstdc ++ до сих пор не реализованы эти специализации, даже в версии gcc 4.7. - person bames53; 18.06.2012
comment
Как вы управляете utf-16 BE или utf-16 LE и можете переключаться между ними (при записи в файл)? - person Sandburg; 18.11.2019
comment
@Sandburg Одним из параметров шаблона фасетов codecvt UTF является codecvt_mode, который позволяет вам указывать такие параметры, как порядок байтов и спецификации. en.cppreference.com/w/cpp/locale/codecvt_mode - person bames53; 05.06.2020

Вы смотрели Boost.Locale? Эта страница, в частности, описывает, как преобразовывать UTF в UTF и как интегрировать его с IOStreams.

person thehouse    schedule 18.06.2012

Я бы посоветовал взглянуть на:

Преобразование C ++ std :: string в строку в кодировке UTF-16-LE

И проверьте функцию iconv. Это библиотека C, никаких требований для C ++ 11.

Также имеется специальная библиотека iconv для Win32 по адресу https://github.com/win-iconv/win-iconv.

person JYG    schedule 09.10.2018