Чтение файлов Unicode - PullRequest
       24

Чтение файлов Unicode

3 голосов
/ 16 июля 2009

У меня проблема с чтением и использованием содержимого из файлов Unicode.

Я работаю над сборкой релиза Unicode и пытаюсь прочитать содержимое из файла Unicode, но данные содержат странные символы, и я не могу найти способ конвертировать данные в ASCII. *

Я использую fgets. Я пробовал fgetws, WideCharToMultiByte и много функций, которые я нашел в других статьях и постах, но ничего не получалось.

Ответы [ 6 ]

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

Поскольку вы упоминаете WideCharToMultiByte, я предполагаю, что вы имеете дело с Windows.

"прочитать содержимое из файла Unicode ... найти способ конвертировать данные в ASCII"

Это может быть проблемой. Если вы конвертируете Unicode в ASCII (или другую унаследованную кодовую страницу), вы рискуете испортить / потерять данные. Поскольку вы «работаете над сборкой релиза Unicode», вам нужно прочитать Unicode и остаться Unicode.

Таким образом, ваш последний буфер должен быть wchar_t (или WCHAR, или CStringW, то же самое).

Таким образом, ваш файл может быть utf-16 или utf-8 (utf-32 довольно редко). Для utf-16 также может иметь значение порядковый номер. Если есть спецификация, которая очень поможет.

Быстрые шаги:

  • открыть файл с wopen или _wfopen в двоичном виде
  • чтение первых байтов для идентификации кодировки с использованием спецификации
  • если кодировка utf-8, прочитать в байтовом массиве и преобразовать в wchar_t с WideCharToMultiByte и CP_UTF8
  • , если кодировка utf-16be (big endian) читается в массиве wchar_t и _swab
  • если кодировка utf-16le (little-endian) читается в массиве wchar_t и все готово

Также (если вы используете более новую Visual Studio), вы можете воспользоваться расширением MS до _wfopen. Он может принимать кодировку как часть режима (что-то вроде _wfopen(L"newfile.txt", L"rw, ccs=<encoding>"); с кодировкой UTF-8 или UTF-16LE). Он также может определять кодировку на основе спецификации.

Предупреждение: кроссплатформенность проблематична, wchar_t может быть 2 или 4 байта, процедуры преобразования не переносимы ...

Полезные ссылки:

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

Предполагаемый способ обработки кодировок - позволить системе локали сделать это.

Вы должны установить правильную локаль, прежде чем открывать свой поток.

Кстати, вы пометили свой вопрос C ++, вы написали о fgets и fgetws, но не IOStreams; ваша проблема C ++ или C?

Для C:

#include <locale.h>
setlocale(LC_ALL, ""); /* at least LC_CTYPE */

Для C ++

#include <locale>
std::locale::global(std::locale(""));

Тогда широкий IO (wstream, fgetws) должен работать, если ваша среда работает правильно установить для Unicode. Если нет, вам придется изменить свою среду (я не как это работает под Windows, для Unix, установка переменной LC_ALL Кстати, см. locale -a для поддерживаемых значений). В качестве альтернативы, замена пустая строка по языку также будет работать, но тогда вы жестко локали в вашей программе, и ваши пользователи, возможно, не оценят это.

Если ваша система не поддерживает адекватную локаль, в C ++ есть возможность написать фасет для конвертации самостоятельно. Но что снаружи объема этого ответа.

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

Unicode - это отображение числовых кодов в символы. Шаг перед Unicode - это кодировка файла: как преобразовать несколько последовательных байтов в числовой код? Вы должны проверить, хранится ли файл как big-endian, little-endian или как-то еще.

Часто спецификация (маркер порядка байтов) записывается как первые два байта в файле: FF FE или FE FF.

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

Нам понадобится больше информации, чтобы ответить на вопрос (например, пытаетесь ли вы прочитать файл Unicode в буфер char или буфер wchar_t? Какую кодировку использует файл?), Но сейчас Возможно, вы захотите убедиться, что вы не столкнулись с этой проблемой , если ваш файл Unicode и вы используете fgetws в текстовом режиме.

При потоковом вводе-выводе Unicode функция работает в текстовом режиме, исходный или целевой поток предполагается последовательность многобайтовых персонажи. Поэтому Юникод функции потокового ввода многобайтовые символы в ширину символы (как будто при вызове функция mbtowc). По той же причине, функции потокового вывода Unicode конвертировать широкие символы в многобайтовые символы (как будто при вызове функция wctomb).

0 голосов
/ 21 июля 2009

Вы НЕ МОЖЕТЕ надежно конвертировать Unicode, даже UTF-8, в ASCII. Наборы символов («плоскости» в документации Unicode) не отображаются обратно в ASCII - поэтому Unicode существует в первую очередь.

0 голосов
/ 17 июля 2009

Во-первых: я предполагаю, что вы пытаетесь прочитать кодировку UTF8-Unicode (так как вы можете читать некоторые символы). Вы можете проверить это, например, в Notpad ++

Для вашей проблемы - я бы предложил использовать какую-то библиотеку. Вы можете попробовать QT , QFile поддерживает Unicode (как и остальная часть библиотеки).

Если это слишком много, используйте специальную юникод-библиотеку, например: http://utfcpp.sourceforge.net/.

И узнайте о Юникоде: http://en.wikipedia.org/wiki/Unicode. Там вы найдете ссылки на различные кодировки Юникода.

...