在Perl中将UTF8字符串转换为ASCII

时间:2010-09-04 15:14:03

标签: perl utf-8 ascii

我已经尝试了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 个答案:

答案 0 :(得分:19)

答案取决于您希望如何使用标题。有三种基本方法:

  • 表示UTF-8编码字符串的字节。

如果您希望将UTF-8编码的字符串存储在应用程序之外,无论是在磁盘上还是通过网络发送或在程序范围之外的任何内容中,都应该使用这种格式。

  • 一串Unicode字符。

字符的概念是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来学习perlunitutperlunifaqperlunicodeperluniintroEncode

答案 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)");