Почему iconv может преобразовывать предварительно составленную форму, а не разложенную форму «É» (из UTF-8 в CP1252) - PullRequest
8 голосов
/ 27 марта 2012

Я использую библиотеку iconv для взаимодействия с современным источником ввода, который использует UTF-8, к устаревшей системе, которая использует Latin1, иначе CP1252 (расширенный набор ISO-8859-1).

Интерфейс недавно не смог преобразовать французскую строку "Éducation", где "É" был закодирован как шестнадцатеричный 45 CC 81. Обратите внимание, что кодировка назначения имеет символ «É», закодированный как C9.

Почему iconv не может преобразовать это "É"? Я проверил, что инструмент командной строки iconv, доступный в MacOS X 10.7.3, говорит, что он не может конвертировать, и что модуль PERL iconv тоже выходит из строя.

Это тем более удивительно, что предварительно составленная форма символа "É" (закодированная как C3 89) преобразуется просто отлично.

Это ошибка с iconv или я что-то упустил?

Обратите внимание, что у меня также возникает та же проблема, если я пытаюсь выполнить преобразование из UTF-16 (где "É" кодируется как составной 00 C9 или 00 45 03 01 разложенный).

Ответы [ 2 ]

5 голосов
/ 18 апреля 2014

К сожалению, iconv действительно не работает с разложенными символами в UTF-8, за исключением версии, установленной в Mac OS X.

При работе с именами файлов Mac вы можете использовать iconv с " utf8-mac"опция набора символов.Он также учитывает несколько особенностей разложенной формы Mac .

Однако версии iconv или libiconv не для Mac не поддерживают это, и я не смог найти источники, используемые на Mac, которые предоставляют такую ​​поддержку.

Я согласен с вами, что iconv долженуметь работать как с NFC, так и с NFD-формами UTF8, но пока кто-то не исправит источники, мы должны обнаружить это вручную и разобраться с этим, прежде чем передавать вещи в iconv.

Столкнувшись с этой досадной проблемой, я использовал PerlЮникод :: Нормализовать модуль согласно предложению Юкки.

#!/usr/bin/perl

use Encode qw/decode_utf8 encode_utf8/;
use Unicode::Normalize;

while (<>) {
    print encode_utf8( NFC(decode_utf8 $_) );
}
0 голосов
/ 27 марта 2012

Используйте нормализатор (в данном случае к форме нормализации C) перед вызовом iconv.

Программа, которая работает с кодировками символов (различными представлениями символов или, точнее, кодом)следует ожидать, что точки, как последовательности байтов) и преобразование между ними будут рассматривать предварительно составленные и составные формы как отдельные.Разложенный É представляет собой две кодовые точки и, как таковой, отличается от предварительно составленной É, которая представляет собой одну кодовую точку.

...