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

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

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

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

3 ответа

Решение

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

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

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

Самый простой пример, который я могу найти, который охватывает все базы, взят из фасета кодека UTF-8 Boost, с примером, который специально пытается кодировать 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), взгляните на следующее:

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

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

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

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

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

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

Другие вопросы по тегам