Преобразование строки 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)");