Ответ 1
С++ поддерживает кодирование символов с помощью std::locale
и фасет std::codecvt
. Общая идея состоит в том, что объект locale
описывает аспекты системы, которые могут варьироваться от культуры к культуре, (человеческого) языка и языка. Эти аспекты разбиваются на facet
s, которые являются аргументами шаблона, которые определяют, как строятся объекты, зависящие от локализации (включая потоки ввода-вывода). Когда вы читаете с istream
или записываете в ostream
, фактическая запись каждого символа фильтруется через грани местности. Границы охватывают не только кодирование типов Unicode, но и такие разнообразные функции, как то, как большие числа записываются (например, с запятыми или периодами), валютой, временем, капитализацией и множеством других деталей.
Однако только потому, что средства существуют для кодирования, не означает, что стандартная библиотека фактически обрабатывает все кодировки, а также не делает такой код простым и правильным. Даже такие основные вещи, как размер персонажа, который вы должны читать (не говоря уже о части кодирования), сложны, так как wchar_t
может быть слишком маленьким (искажать ваши данные) или слишком большим (тратить пространство), а наиболее распространенным компиляторы (например, Visual С++ и Gnu С++) различаются по степени их реализации. Поэтому вам обычно нужно найти внешние библиотеки для фактической кодировки.
- iconv, как правило, подтверждают правильность, но примеры того, как связать его с механизмом С++, трудно найти.
- jla3ep упоминает libICU, который является очень тщательным, но API С++ не пытается хорошо играть со стандартом (насколько я могу судить: вы можете сканировать примеры, чтобы узнать, можете ли вы сделать лучше.)
Самый простой пример, который я могу найти, который охватывает все базы, - от Boost UTF-8 codecvt facet, с примером, который специально пытается кодировать UTF-8 (UCS4) для использования потоками ввода-вывода. Это похоже на это, хотя я не предлагаю просто копировать его дословно. Чтобы понять это (и я не претендую на это), источник требует больше:
typedef wchar_t ucs4_t;
std::locale old_locale;
std::locale utf8_locale(old_locale,new utf8_codecvt_facet<ucs4_t>);
...
std::wifstream input_file("data.utf8");
input_file.imbue(utf8_locale);
ucs4_t item = 0;
while (ifs >> item) { ... }
Чтобы узнать больше о локалях и как они используют грани (в том числе codecvt
), взгляните на следующее:
- Натан Майерс подробное объяснение локалей и граней. Майерс был одним из разработчиков концепции локали. У него более формальная документация, если вы хотите пробраться через него.
- Реализация стандартной библиотеки Apache (ранее RogueWave) имеет полный список фасет.
- Nicolai Josuttis Стандартная библиотека С++ Глава 14 посвящена теме.
- Анжелика Лангер и Клаус Крефт Стандартные IOStreams и локали я ++ посвящают целую книгу.