Обработка символов Юникода в C ++ - PullRequest
0 голосов
/ 17 февраля 2012

У меня есть файл, который содержит текст Unicode в неустановленной кодировке.Я хочу отсканировать этот файл, чтобы найти любые арабские кодовые точки в диапазоне от U + 0600 до U + 06FF, и сопоставить каждую соответствующую кодовую точку Unicode с байтом ASCII, чтобы вновь создаваемый файл состоял из чисто символов ASCII.со всеми кодами под 128.

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

ПРИМЕЧАНИЕ : файл состоит из подмножестваиз набора символов Unicode, а размер подмножества меньше, чем размер символов ASCII.Поэтому я могу сделать отображение 1: 1 из этого конкретного подмножества Unicode в ASCII.

Ответы [ 3 ]

4 голосов
/ 17 февраля 2012

Это либо невозможно, либо тривиально.Вот тривиальные подходы:

  • Если ни одна кодовая точка не превышает 127, просто запишите ее в ASCII.Готово.

  • Если некоторые кодовые точки превышают 127, вы должны выбрать, как их представлять в ASCII.Обычной стратегией является использование синтаксиса XML, как в α для U + 03B1.Это займет до 8 символов ASCII для каждой транскрибируемой кодовой точки Unicode транс-ASCII.

Невозможные, которые я оставлю в качестве упражнения для оригинального плаката.Я даже не буду упоминать глупые, но возможные (читай: глупые) подходы, так как это легион.Уничтожение данных является серьезным преступлением при обработке данных и должно рассматриваться как таковое.

Обратите внимание, что я предполагаю, что под символом Unicode вы на самом деле имеете в виду «кодовая точка Unicode»;то есть видимый программисту персонаж.Для символов, видимых пользователю, вместо этого вам понадобится графема Unicode (кластер).

Кроме того, если вы сначала не нормализуете свой текст, вы будете ненавидеть мир.Я предлагаю НФД.


РЕДАКТИРОВАТЬ

После дальнейшего разъяснения оригинальным постером кажется, что то, что он хочет сделать, очень легко сделать с помощью существующих инструментов без написания новой программы.Например, это преобразует определенный набор арабских символов из входного файла UTF-8 в выходной файл ASCII:

$ perl -CSAD -Mutf8 -pe 'tr[ابتثجحخد][abttjhhd]' < input.utf8 > output.ascii

, который обрабатывает только следующие кодовые точки:

U+0627 ‭ ا  ARABIC LETTER ALEF
U+0628 ‭ ب  ARABIC LETTER BEH
U+0629 ‭ ة  ARABIC LETTER TEH MARBUTA
U+062A ‭ ت  ARABIC LETTER TEH
U+062B ‭ ث  ARABIC LETTER THEH
U+062C ‭ ج  ARABIC LETTER JEEM
U+062D ‭ ح  ARABIC LETTER HAH
U+062E ‭ خ  ARABIC LETTER KHAH
U+062F ‭ د  ARABIC LETTER DAL

Таквам придется расширить его до любого отображения, которое вы хотите.

Если вы хотите использовать его в сценарии вместо инструмента командной строки, это также легко, плюс вы можете говорить о символах по имени, задаваядо отображения, такого как:

 "\N{ARABIC LETTER ALEF}"   =>  "a",
 "\N{ARABIC LETTER BEH}"    =>  "b",
 "\N{ARABIC LETTER TEH}"    =>  "t",
 "\N{ARABIC LETTER THEH}"   =>  "t",
 "\N{ARABIC LETTER JEEM}"   =>  "j",
 "\N{ARABIC LETTER HAH}"    =>  "h",
 "\N{ARABIC LETTER KHAH}"   =>  "h",
 "\N{ARABIC LETTER DAL}"    =>  "d",

Если предполагается, что это компонент в более крупной программе на C ++, то, возможно, вы захотите реализовать это на C ++, возможно, но не обязательно, используя библиотеку ICU4C,которая включает в себя поддержку транслитерации.

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

1 голос
/ 17 февраля 2012

Вы не можете прочитать данные, если не знаете формат. Откройте файл с помощью Microsoft Word и перейдите к «Сохранить как», «Другие форматы», «Простой текст (.txt)», сохранить. В окне преобразования выберите «Другая кодировка», «Юникод» (который является UTF16LE) и «ОК». Этот файл теперь сохраняется как UTF16LE.

std:ifstream infile("myfile.txt", std::ios::binary); //open stream
infile.seekg (0, ios::end); //get it's size
int length = infile.tellg();
infile.seekg (0, ios::beg);
std::wstring filetext(length/2); //allocate space
ifstream.read((char*)&filetext[0], length); //read entire file
std::string final(length/2);
for(int i=0; i<length/2; ++i) { //"shift" the variables to "valid" range
    if (filetext[length/2] >= 0x600 && filetext[length/2] <= 0xFF)
        final[length/2] = filetext[length/2]-0x600;
    else
        throw std::exception("INVALID CHARACTER");
}
//done

Предупреждения повсюду: я очень сомневаюсь, что это приведет к тому, что вы хотите, но это лучшее, чем можно управлять, поскольку вы не сообщили нам перевод, который необходимо выполнить, или формат файла. Кроме того, я предполагаю, что ваш компьютер и компилятор такие же, как мой. Если нет, то некоторые или все из этого могут быть неправильными, но это лучшее, что я могу сделать с этой недостающей информацией, которую вы нам не сообщили.

0 голосов
/ 18 февраля 2012

Чтобы разобрать кодовые точки Unicode, вы должны сначала декодировать файл в его некодированное представление Unicode (что эквивалентно UTF-32). Чтобы сделать это, вам сначала нужно знать, как файл был закодирован, чтобы его можно было декодировать. Например, кодовые точки Unicode U+0600 и U+06FF кодируются как 0xD8 0x80 и 0xDB 0xBF в UTF-8, как 0x00 0x06 и 0xFF 0x06 в UTF-16LE, как 0x06 0x00 и 0x06 0xFF в UTF -16BE и т. Д.

Если файл начинается с спецификации, то вы знаете точную используемую кодировку и можете соответствующим образом интерпретировать остальную часть файла. Например, спецификация UTF-8 - 0xEF 0xBB 0xBF, UTF-16LE - 0xFF 0xFE, UTF-16BE - 0xFE 0xFF и т. Д.

Если файл не начинается с спецификации, то вам необходимо проанализировать данные и выполнить их анализ для определения кодировки, но это не на 100% надежно. Хотя довольно просто обнаружить кодировки UTF, практически невозможно обнаружить кодировки Ansi с какой-либо степенью надежности. Даже обнаружение кодировок UTF без наличия спецификации может иногда приводить к ложным результатам (прочитайте , , , и , ).

Никогда не догадывайтесь, вы рискуете потерять данные. Если вы не знаете точную кодировку, попросите пользователя.

...