2009-07-16 4 views
3

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

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

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

+4

Возможно, вы захотите уточнить, что вы подразумеваете под «Unicode». UTF-8? UTF-16? –

+1

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

+3

Обратите внимание, что не может быть ASCII-представление «странных символов» в вашем файле. –

ответ

7

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

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

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

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

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

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

  • открыть файл с wopen или _wfopen как бинарный
  • прочитать первые байты для идентификации кодирования с использованием спецификации
  • , если кодировка UTF-8, чтения в байте массив и конвертировать в wchar_t с WideCharToMultiByte и CP_UTF8
  • , если кодировка UTF-16BE (большой байтов) чтения в wchar_t массиве и _swab
  • , если кодировка UTF-16LE (маленький обратный порядок байт) чтения в wchar_t массиве, и вы сделали

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

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

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

+0

Это сообщение: «Если вы конвертируете Unicode в ASCII (или другую устаревшую страницу кода), вы столкнетесь с риском развращения/потери данных» –

+0

К сожалению, мой комментарий здесь должен быть опубликован как ответ на вопрос. * Ваш * ответ правильный. – DaveE

1

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

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

1

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

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

1

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

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

BTW вы помечаете свой вопрос 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++ есть возможность написать фасет для преобразования самостоятельно. Но это за пределами сферы действия этого ответа.

0

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

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

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

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

0

НЕЛЬЗЯ надежно конвертировать Unicode, даже UTF-8, в ASCII. Наборы символов («плоскости» в документации Unicode) не отображаются в ASCII - вот почему Unicode существует в первую очередь.

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