C ++ Unicode файл IO - PullRequest
       18

C ++ Unicode файл IO

4 голосов
/ 19 июля 2009

Мне нужна библиотека file io, которая может дать моей программе интерфейс utf-16 (little-endian), но может обрабатывать файлы в других кодировках, в основном ascii (только для ввода), utf-8, utf-16, utf-32 / ucs4, включая байты в младшем и старшем порядке.

Посмотрев вокруг единственной библиотеки, которую я нашел, была библиотека ICU ustdio.h.

Я попробовал, однако я даже смог заставить его работать с очень простым кусочком текста, и документации по его использованию практически нет, только справочная страница файла ICU, в которой нет примеров и очень мало деталей (например, сделав UFILE из существующего ФАЙЛА, безопасно ли использовать другие функции, которые принимают ФАЙЛ *? вместе с несколькими другими ...).

Кроме того, это, скорее, библиотека C ++, которая может предоставить мне широкий интерфейс потока через интерфейс в стиле C ...

std::wstring str = L"Hello World in UTF-16!\nAnother line.\n";
UFILE *ufile = u_fopen("out2.txt", "w", 0, "utf-16");
u_file_write(str.c_str(), str.size(), ufile);
u_fclose(ufile);

выход

Hello World in UTF-16!਍䄀渀漀琀栀攀爀 氀椀渀攀⸀ഀ

шестигранный

FF FE 48 00 65 00 6C 00 6C 00 6F 00 20 00 57 00
6F 00 72 00 6C 00 64 00 20 00 69 00 6E 00 20 00
55 00 54 00 46 00 2D 00 31 00 36 00 21 00 0D 0A
00 41 00 6E 00 6F 00 74 00 68 00 65 00 72 00 20
00 6C 00 69 00 6E 00 65 00 2E 00 0D 0A 00

РЕДАКТИРОВАТЬ: правильный вывод на окна будет:

FF FE 48 00 65 00 6C 00 6C 00 6F 00 20 00 57 00 
6F 00 72 00 6C 00 64 00 20 00 69 00 6E 00 20 00 
55 00 54 00 46 00 2D 00 31 00 36 00 21 00 0D 00 
0A 00 41 00 6E 00 6F 00 74 00 68 00 65 00 72 00
20 00 6C 00 69 00 6E 00 65 00 2E 00 0D 00 0A 00

Ответы [ 5 ]

4 голосов
/ 20 июля 2009

Я успешно работал с библиотекой EZUTF , размещенной в CodeProject: Высокопроизводительные подпрограммы ввода-вывода текстового файла Unicode для C ++

4 голосов
/ 20 июля 2009

Проблема, которую вы видите, связана с преобразованием перевода строки. К сожалению, он сделан на уровне байтов (после преобразования кода) и не знает о кодировке. IOWs, вы должны отключить автоматическое преобразование (открыв файл в двоичном режиме с флагом «b») и, если вы хотите расширить 0A00 до 0D00A00, вам придется сделать это самостоятельно.

Вы упоминаете, что предпочитаете широкополосный интерфейс C ++, поэтому я в общих чертах опишу, что я сделал для достижения этой цели в нашем программном обеспечении:

  • Напишите фасет std :: codecvt с помощью ICU UConverter для выполнения преобразований.
  • Используйте std :: wfstream, чтобы открыть файл
  • imbue () ваш пользовательский кодекв в wfstream
  • Откройте wfstream с двоичным флагом, чтобы отключить автоматическое (и ошибочное) преобразование перевода строки.
  • Напишите «WNewlineFilter», чтобы выполнить преобразование перевода строки в wchars. Используйте вдохновение от boost :: iostreams :: newline_filter
  • Используйте boost :: iostreams :: filtering_wstream , чтобы связать wfstream и WNewlineFilter вместе в виде потока.
2 голосов
/ 19 июля 2009

UTF8-CPP дает вам преобразование между UTF-8, 16 и 32. Очень хорошая и легкая библиотека.

Об ICU, некоторые комментарии создателя UTF8-CPP:

Библиотека ICU. Это очень мощный, полный, многофункциональный, зрелый и широко используемый. Также большой, навязчивый, не универсальный, и не очень хорошо играет со стандартной библиотекой. я определенно рекомендую смотреть на реанимацию даже если вы не планируете его использовать.

:)

1 голос
/ 19 июля 2009

Вы можете попробовать библиотеку iconv ( libiconv ).

1 голос
/ 19 июля 2009

Я думаю, что проблемы связаны с переводом строки 0D 0A 00. Вы можете попробовать, если другие разрывы строки, такие как \r\n или использование только LF или CR, работают (лучше всего будет использовать \r, я полагаю)

РЕДАКТИРОВАТЬ: Кажется, 0D 00 0A 00 это то, что вы хотите, поэтому вы можете попробовать

std::wstring str = L"Hello World in UTF-16!\15\12Another line.\15\12";
...