如何在Perl中将输入文件转换为UTF-8编码?

时间:2009-10-23 09:08:18

标签: perl unicode utf-8 character-encoding

我已经知道如何将文件的非utf8编码内容逐行转换为UTF-8编码,使用类似下面的代码:

# outfile.txt is in GB-2312 encode    
open my $filter,"<",'c:/outfile.txt'; 

while(<$filter>){
#convert each line of outfile.txt to UTF-8 encoding   
    $_ = Encode::decode("gb2312", $_); 
...}

但是我认为Perl可以直接将整个输入文件编码为UTF-8格式,所以我尝试了类似

的内容
#outfile.txt is in GB-2312 encode
open my $filter,"<:utf8",'c:/outfile.txt'; 

(Perl说像“utf8”\ xD4“没有映射到Unicode”)

open my $filter,"<",'c:/outfile.txt'; 
$filter = Encode::decode("gb2312", $filter); 

(Perl在未打开的文件句柄上说“readline()!”

它们不起作用。但有没有办法直接将输入文件转换为UTF-8编码?

更新

看起来事情并不像我想象的那么简单。我现在可以以环形方式将输入文件转换为UTF-8代码。我首先打开输入文件,然后将其内容编码为UTF-8,然后输出到新文件,然后打开新文件以进行进一步处理。这是代码:

open my $filter,'<:encoding(gb2312)','c:/outfile.txt'; 
open my $filter_new, '+>:utf8', 'c:/outfile_new.txt'; 
print $filter_new $_ while <$filter>; 
while (<$filter_new>){
...
} 

但这是太多的工作,它比简单地逐行编码$ filter的内容更麻烦。

2 个答案:

答案 0 :(得分:5)

我想我误解了你的问题。我想你想要做的是读取非UTF-8编码的文件,然后在程序中使用UTF-8数据。这更容易。使用正确的编码读取数据后,Perl在内部将其表示为UTF-8。所以,做你必须做的事。

当您将其写回时,请使用您想要保存的任何编码。但是,您不必将其放回文件中即可使用它。


旧回答

Perl I / O层只读取数据,假设它已经正确编码。它不会为你转换编码。通过告诉open使用utf8,你告诉它已经是utf8。

您必须像显示的那样使用Encode模块(除非您想编写自己的I / O层)。您可以将字节转换为UTF-8,或者如果您知道编码,则可以从一种编码转换为另一种编码。由于看起来您已经知道编码,因此您可能需要from_to()函数。

如果您刚刚开始使用Perl和Unicode,请在执行任何操作之前先通过Juerd's Perl Unicode Advice

答案 1 :(得分:4)

:编码层将返回UTF-8,适合perl的使用。也就是说,perl会将每个字符识别为一个字符,即使它们是多个字节。根据您接下来要对数据执行的操作,这可能就足够了。

但是如果你正在对perl尝试将它从utf8降级的数据做一些事情,你要么告诉perl不要(例如,做一个binmode(STDOUT,“:utf8”)告诉perl输出to stdout应该是utf8),或者你需要让perl将你的utf8视为二进制数据(分别解释每个字节,并且对utf8字符一无所知。)

为此,您只需要在开放时应用其他图层:

open my $foo, "<:encoding(gb2312):bytes", ...;

请注意,以下内容的输出结构相同:

perl -we'open my $foo, "<:encoding(gb2312):bytes", "foo"; $bar = <$foo>; print $bar'
perl -CO -we'open my $foo, "<:encoding(gb2312)", "foo"; $bar = <$foo>; print $bar'

但在一种情况下,perl知道读取的数据是utf8(因此长度($ bar)将报告utf8字符的数量)并且必须明确告知(通过-CO)STDOUT将接受utf8,并且另一方面,perl对数据没有任何假设(因此长度($ bar)将报告字节数),并按原样打印出来。