2009-08-13 2 views
12

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

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

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

+2

Как наполнить потоки с помощью локали. http://stackoverflow.com/questions/207662/writing-utf16-to-file-in-binary-mode/208431#208431 –

ответ

21

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

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

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

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

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), обратите внимание на следующем :

+1

Хорошее резюме. Вы можете добавить http://www.amazon.com/dp/0201183951 в свой список книг. Это самое тщательное отношение к проблеме, которую я знаю. – sbi

+0

sbi: добавлена ​​книга в список. Спасибо за хорошую ссылку. – quark

1

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

Raymond Chen один раз wrote a series illustrating how to work with different wide character stream/string types.

4

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

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

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

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

+1

Я думаю, что немного правильнее сказать, что абзацы 'ifstream' над кодировкой. Он использует его через средства нижнего уровня: локали (для стандартного C++) и функции i18n для ОС или библиотеки. то есть 'ifstream', возможно, не волнует, но вам все равно, что он вызывает в этом случае. – quark

+3

'locales' не имеет ничего общего с кодировками Unicode. Когда вы устанавливаете языковой стандарт, вы просто указываете «iostream», как он должен представлять символы на консоли. Но вы не можете обнаружить кодировку * файла *. И нельзя отличить ANSI от UTF-8, используя 'ifstream'. –

Смежные вопросы