(w) ifstream поддерживает различные кодировки

Когда я читаю текстовый файл в широкую строку символов (std :: wstring) с помощью wifstream, реализует ли реализация streamа разные кодировки, т. Е. Может ли она использоваться для чтения, например, файлов ASCII, UTF-8 и UTF-16?

Если нет, что мне делать?

(Мне нужно прочитать весь файл, если это имеет значение)

C ++ поддерживает кодировки символов с помощью std::locale и facet std::codecvt . Общая идея состоит в том, что locale объект описывает аспекты системы, которые могут варьироваться от культуры к культуре, (человеческого) языка к языку. Эти аспекты разбиваются на facet s, которые являются аргументами шаблона, которые определяют, как строятся объекты, зависящие от локализации (включая streamи ввода-вывода). Когда вы читаете из istream или пишите в ostream , фактическая запись каждого символа фильтруется через грани локали. Границы охватывают не только кодирование типов Unicode, но и такие разнообразные функции, как то, как большие числа записываются (например, с запятыми или периодами), валютой, временем, капитализацией и множеством других деталей.

Однако только потому, что средства существуют для кодирования, не означает, что стандартная библиотека фактически обрабатывает все кодировки, а также не делает такой код простым и правильным. Даже такие основные вещи, как размер символа, который вы должны читать (не говоря уже о части кодирования), сложны, так как wchar_t может быть слишком маленьким (искажать ваши данные) или слишком большим (тратить пространство) и наиболее распространенными компиляторами ( например Visual C ++ и Gnu C ++) различаются по степени их реализации. Поэтому вам обычно нужно найти внешние библиотеки для фактической кодировки.

  • iconv обычно признается правильным, но примеры того, как связать его с механизмом C ++, найти сложно.
  • jla3ep упоминает libICU , который очень тщательный, но C ++ API не пытается хорошо играть со стандартом (насколько я могу судить: вы можете сканировать примеры, чтобы увидеть, можете ли вы сделать лучше).

Самый простой пример, который я могу найти, который охватывает все базы, относится к фасету UECF-8 от Boost, с примером, который специально пытается кодировать UTF-8 (UCS4) для использования streamами ввода-вывода. Это похоже на это, хотя я не предлагаю просто копировать его дословно. Чтобы понять это, требуется немного больше копания в источнике (и я не утверждаю):

 typedef wchar_t ucs4_t; std::locale old_locale; std::locale utf8_locale(old_locale,new utf8_codecvt_facet); ... std::wifstream input_file("data.utf8"); input_file.imbue(utf8_locale); ucs4_t item = 0; while (ifs >> item) { ... } 

Чтобы узнать больше о локалях и как они используют грани (в том числе codecvt ), взгляните на следующее:

  • Натан Майерс имеет полное объяснение мест и аспектов . Майерс был одним из разработчиков концепции локали. У него есть более формальная документация, если вы хотите пробраться через нее.
  • Внедрение стандартной библиотеки Apache (ранее RogueWave) имеет полный список фасетов .
  • Nicolai Josuttis « Стандартная библиотека C ++» Глава 14 посвящена теме.
  • Стандартные IOStreams и локали Angelika Langer и Klaus Kreft посвящают целую книгу.

ifstream не заботится о кодировании файла. Он просто считывает символы (байты) из файла. wifstream читает широкие байты ( wchar_t ), но он все еще ничего не знает о кодировке файлов. wifstream достаточно хорош для UCS-2 – кодировка с фиксированной длиной символов для Unicode (каждый символ представлен двумя байтами).

Вы можете использовать библиотеку IBM ICU для работы с файлами Unicode.

Международный компонент для Unicode (ICU) – это зрелый переносимый набор библиотек C / C ++ и Java для поддержки Unicode, интернационализации программного обеспечения (I18N) и глобализации (G11N), что дает приложениям одинаковые результаты на всех платформах.

ICU выпускается под неограниченной лицензией с открытым исходным кодом, которая подходит для использования как с коммерческим программным обеспечением, так и с другим открытым исходным кодом или бесплатным программным обеспечением.

Конструкция широкоформатных и широкоформатных streamов предварительной передачи UTF-8, UTF-16 и Unicode. Если вы хотите получить техническую информацию, стандартная строка и стандартный stream не обязательно работают с ASCII (это просто то, что в основном все компьютеры там используют ASCII, у вас может быть машина EBCDIC).

Раймонд Чен однажды написал серию, иллюстрирующую, как работать с разными типами символов / строк .

  • Выход UTF-8 от PowerShell
  • Давайте будем гением компьютера.