我已经尝试了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字符串结束。任何想法将不胜感激。感谢。
答案 0 :(得分:19)
答案取决于您希望如何使用标题。有三种基本方法:
如果您希望将UTF-8编码的字符串存储在应用程序之外,无论是在磁盘上还是通过网络发送或在程序范围之外的任何内容中,都应该使用这种格式。
字符的概念是Perl的内部。当您执行Encode::decode_utf8
时,会尝试将一堆字节转换为字符串,如Perl所示。除了通过在输入上解码UTF-8字节并在输出上将它们编码为UTF-8字节之外,Perl VM(以及编写Perl代码的程序员)不能外化该概念。例如,你的程序接收两个字节作为输入,你知道它们代表UTF-8编码的字符,比方说0xC3 0xB6
。在这种情况下,decode_utf8
返回一个表示,而不是两个字节,看到一个字符:ö
。
然后,您可以继续在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本身就是有损操作,因为大多数Unicode字符不是ASCII字符。当你试图强制使用Unicode时,你要么被迫删除字符串中不是ASCII的每个字符,要么尝试从Unicode字符映射到它们最接近的ASCII等价物(这在绝大多数情况下是不可能的)字符串到ASCII。
由于您有广泛的字符警告,这意味着您正在尝试操纵(可能输出)无法表示为ASCII或ISO-8859-1的Unicode字符。
如果您不需要将XML文档中的标题作为字符串进行操作,我建议您将其保留为UTF-8字节(我提到您应该注意不要在字符串中混合字节和字符)。如果你确实需要操作它,那么解码,操作和输出就会用UTF-8对它进行编码。
如需进一步阅读,请使用perldoc
来学习perlunitut
,perlunifaq
,perlunicode
,perluniintro
和Encode
。
答案 1 :(得分:6)
虽然这是一个老问题,但我只花了几个小时(!)尝试或多或少做同样的事情!即:从UTF-8 XML文件中读取数据,并将该数据转换为Windows-1252代码页(我也可以使用Latin1,ISO-8859-1等),以便能够创建带有重音字母的文件名
经过多次实验,甚至更多搜索,我终于设法让转换工作了。 “技巧”是使用Encode :: 编码而不是Encode :: decode 。
例如,考虑到原始问题中的代码,从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});
我希望这可以帮助其他人遇到类似的问题!
答案 2 :(得分:2)
您可以使用以下行简单地删除警告。这假设您要使用UTF8,这通常不应该是一个问题。
binmode(STDOUT, ":encoding(utf8)");