Red*_*ick 6 unicode perl utf-8
当我使用LWP :: UserAgent检索以UTF-8编码的内容时,似乎LWP :: UserAgent无法正确处理编码.
这是通过命令将命令提示符窗口设置为Unicode后的输出chcp 65001注意,这最初给出了一切都很好的外观,但我认为它只是shell重新组装字节并解码UTF-8,从另一个输出中你可以看到perl本身并没有正确处理宽字符.
C:\>perl getutf8.pl ====================================================================== HTTP/1.1 200 OK Connection: close Date: Fri, 31 Dec 2010 19:24:04 GMT Accept-Ranges: bytes Server: Apache/2.2.8 (Win32) PHP/5.2.6 Content-Length: 75 Content-Type: application/xml; charset=utf-8 Last-Modified: Fri, 31 Dec 2010 19:20:18 GMT Client-Date: Fri, 31 Dec 2010 19:24:04 GMT Client-Peer: 127.0.0.1:80 Client-Response-Num: 1 <?xml version="1.0" encoding="UTF-8"?> <name>Bud?jovický Budvar</name> ====================================================================== response content length is 33 ....v....1....v....2....v....3....v....4 <name>Bud?jovický Budvar</name> . . . . v . . . . 1 . . . . v . . . . 2 . . . . v . . . . 3 . . . . 3c6e616d653e427564c49b6a6f7669636bc3bd204275647661723c2f6e616d653e < n a m e > B u d ? ? j o v i c k ? ? B u d v a r < / n a m e >
上面你可以看到有效载荷长度是31个字符但是Perl认为它是33.为了确认,在十六进制中,我们可以看到UTF-8序列c49b和c3bd被解释为四个单独的字符而不是两个Unicode字符.
这是代码
#!perl
use strict;
use warnings;
use LWP::UserAgent;
my $ua = LWP::UserAgent->new();
my $response = $ua->get('http://localhost/Bud.xml');
if (! $response->is_success) { die $response->status_line; }
print '='x70,"\n",$response->as_string(), '='x70,"\n";
my $r = $response->decoded_content((charset => 'UTF-8'));
$/ = "\x0d\x0a"; # seems to be \x0a otherwise!
chomp($r);
# Remove any xml prologue
$r =~ s/^<\?.*\?>\x0d\x0a//;
print "Response content length is ", length($r), "\n\n";
print "....v....1....v....2....v....3....v....4\n";
print $r,"\n";
print ". . . . v . . . . 1 . . . . v . . . . 2 . . . . v . . . . 3 . . . . \n";
print unpack("H*", $r), "\n";
print join(" ", split("", $r)), "\n";
请注意,Bud.xml是UTF-8编码而没有BOM.
我怎样才能说服LWP :: UserAgent做正确的事情?
PS最终我想将Unicode数据转换为ASCII编码,即使它意味着用一个问号或其他标记替换每个非ASCII字符.
我接受了Ysth的"升级"答案 - 因为我知道在可能的情况下这是正确的做法.但是,有一种方法可以将数据修复为格式良好的Perl Unicode字符串.
$r = decode("utf8", $r);
Run Code Online (Sandbox Code Playgroud)
我的数据被送到非Perl应用程序,该应用程序在许多位置使用Code to Putty/Reflection/Teraterm终端显示数据.该应用目前正在显示如下内容:
Bud?ä?øjovick?â?¢ Budvar
我将($r = decode("UTF-8", $r)) =~ s/[\x80-\x{FFFF}]/\xFE/g;用来显示应用程序:
Bud?jovick? Budvar
远离CP437将是一项重要工作,因此在中短期内不会发生这种情况.
CPAN有一些有趣的Unicode模块,例如:
Text :: Unidecode将"BudějovickýBudvar"翻译成"Budejovicky Budvar" - 这对我来说似乎不是一个特别令人印象深刻的语音音译尝试,但后来我不会说捷克语.说英语的人可能更喜欢"Bud■jovick■Budvar".
升级到更新的libwwwperl.您正在使用的旧版本仅将decode_content的charset参数用于text/*内容类型; 较新的版本也适用于application/xml或任何以+ xml结尾的版本.