Преобразование строки UTF8 в ASCII в Perl

Я пробовал все, что Google и StackOverflow рекомендовали (что я мог найти), включая использование Encode. Мой код работает, но он просто использует UTF8, и я получаю широкие предупреждения символов. Я знаю, как обойти эти предупреждения, но я не использую UTF8 для чего-либо еще, поэтому я хотел бы просто преобразовать его и не адаптировать остальную часть моего кода для борьбы с ним. Вот мой код:

my $xml = XMLin($content);
# Populate the @titles array with each item title.
my @titles;
for my $item (@{$xml->{channel}->{item}}) {
    my $title = Encode::decode_utf8($item->{title});
    #my $title = $item->{title};
    #utf8::downgrade($title, 1);
    Encode::from_to($title, 'utf8', 'iso-8859-1');
    push @titles, $title;
}
return @titles;

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

3 ответов


ответ зависит от того, как вы хотите использовать название. Существует 3 основных пути:

  • байты, представляющие строку в кодировке UTF-8.

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

  • строка символов Юникода.

в понятие символов является внутренним для Perl. При выполнении Encode::decode_utf8, затем группа байтов пытается быть преобразована в строку символов, как видно из Perl. Perl VM (и программист, пишущий код Perl) не могут экстернализовать эту концепцию, кроме как путем декодирования байтов UTF-8 на входе и кодирования их в байты UTF-8 на выходе. Например, ваша программа получает два байта в качестве входных данных, которые, как вы знаете, представляют кодированные символы UTF-8, скажем 0xC3 0xB6. В таком случае ...--3--> возвращает представление, которое вместо двух байтов видит один символ:ö.

затем вы можете продолжить манипулировать этой строкой в Perl. Чтобы проиллюстрировать разницу дальше, рассмотрим следующий код:

my $bytes = "\xC3\xB6";
say length($bytes); # prints "2"
my $string = decode_utf8($bytes);
say length($string); # prints "1"
  • частный случай ASCII, подмножество UTF-8.

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

поскольку у вас есть широкие предупреждения символов, это означает, что вы пытаетесь манипулировать (возможно, выводить) символами Unicode, которые не могут быть представленным как ASCII или ISO-8859-1.

Если вам не нужно манипулировать заголовком Из вашего XML-документа в виде строки, Я бы предложил вам оставить его как UTF-8 байт (я бы упомянул, что вы должны быть осторожны, чтобы не смешивать байты и символы в строках). Если вам нужно манипулировать им, то декодируйте, манипулируйте и на выходе кодируйте его в UTF-8.

для дальнейшего чтения, пожалуйста, используйте perldoc учиться perlunitut, perlunifaq, perlunicode, perluniintro и Encode.


хотя это старый вопрос, я просто провел несколько часов (!) пытаюсь сделать более или менее то же самое! То есть: прочитайте данные из XML-файла UTF-8 и преобразуйте эти данные в кодовую страницу Windows-1252 (я мог бы также использовать Latin1, ISO-8859-1 и т. д.) для того, чтобы иметь возможность создавать имена с буквы.

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

например, учитывая код в исходном вопросе, правильный (или, по крайней мере,один : -) способ преобразования из UTF-8 будет:

my $title = Encode::encode("Windows-1252", $item->{title});

или

my $title = Encode::encode("ISO-8859-1", $item->{title});

или

my $title = Encode::encode("<your-favourite-codepage-here>", $item->{title});

Я надеюсь, что это помогает другим, имеющим аналогичные проблемы!


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

binmode(STDOUT, ":encoding(utf8)");