如何在 Perl 中将输入文件转换为 UTF-8 编码?
Posted
技术标签:
【中文标题】如何在 Perl 中将输入文件转换为 UTF-8 编码?【英文标题】:How can I convert an input file to UTF-8 encoding in Perl? 【发布时间】:2010-12-09 09:27:32 【问题描述】:我已经知道如何将文件的非 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的内容还要麻烦。
【问题讨论】:
当您在问题中提及警告消息时,请在问题中包含警告消息。 :) @brian,感谢您的建议。 最好使用准确的警告信息 :) 所以,有了这个警告,您需要检查打开的结果(无论如何您都应该这样做)。 工作量太大?只需几行代码,这看起来非常简单且可行。把它包装在一个子程序中,你就完成了。我不确定你为什么用“+>”打开一个文件。 嗯,如果你想读的话,你需要从头开始 【参考方案1】:我想我误解了你的问题。我认为您想要做的是以非 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,然后再做任何事情。
【讨论】:
@brian,感谢您的指导。我认为应该有一些简单的方法可以在打开输入文件时直接将其转换为 UTF-8 编码。但现在看来事情并没有那么简单。我想我可以先打开输入文件,然后将内容编码为 UTF-8,然后以 UTF-8 编码输出到另一个文件,然后打开另一个文件。代码如下: open my $filter,'<:encoding>:utf8', 'c:/f2.txt';打印 $filter_new $_ while ; while ()... 但这工作量太大了。而() 你对工作量太大的看法是错误的。尝试手工完成,然后回来告诉我们 Perl 为您带来了多么容易。今天的孩子们不知道他们有多好。 :) Mike 的直觉是正确的;你可以堆叠层直接做他想要的转换:) 你不能堆叠层,真的。如果你想文件以不同的编码结束,你仍然必须阅读它,你仍然必须编写它。 我很确定(我认为问题的原始部分更清楚一点)他想要的只是转换文件中的数据,而不是文件本身。但是,是的,要做到后者,仅仅阅读是不够的【参考方案2】::encoding 层将返回 UTF-8,适合 perl 的使用。也就是说,perl 会将每个字符识别为一个字符,即使它们是多个字节。根据您接下来要对数据执行的操作,这可能就足够了。
但是,如果您正在处理 perl 将尝试将其从 utf8 降级的数据,您要么需要告诉 perl 不要这样做(例如,执行 binmode(STDOUT, ":utf8") 来告诉 perl 该输出到 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(因此 length($bar) 将报告 utf8 字符的数量)并且必须明确告知(通过 -CO)STDOUT 将接受 utf8,并且在另一个,perl 不对数据做任何假设(因此 length($bar) 将报告字节数),并按原样打印出来。
【讨论】:
以上是关于如何在 Perl 中将输入文件转换为 UTF-8 编码?的主要内容,如果未能解决你的问题,请参考以下文章