我有一个CSV文件,比如win.csv,其文本在windows-1252中编码。首先,我使用iconv在utf8中创建它。
$iconv -o test.csv -f windows-1252 -t utf-8 win.csv
然后我使用以下Perl脚本(utfcsv.pl)读取转换后的CSV文件。
#!/usr/bin/perl
use utf8;
use Text::CSV;
use Encode::Detect::Detector;
my $csv = Text::CSV->new({ binary => 1, sep_char => ';',});
open my $fh, "<encoding(utf8)", "test.csv";
while (my $row = $csv->getline($fh)) {
my $line = join " ", @$row;
my $enc = Encode::Detect::Detector::detect($line);
print "($enc) $line\n";
}
$csv->eof || $csv->error_diag();
close $fh;
$csv->eol("\r\n");
exit;
然后输出如下。
(UFT-8) .........
() .....
即所有行的编码都被检测为UTF-8(或ASCII)。但实际输出似乎不是UTF-8。实际上,如果我将输出保存在文件
上$./utfcsv.pl > output.txt
然后将output.txt的编码检测为windows-1252。
问题:如何在UFT-8中获取输出文本?
注意:
#!/usr/bin/perl
use Encode::Detect::Detector;
open my $in, "<","$ARGV[0]" || die "open failed";
while (my $line = <$in>) {
my $enc = Encode::Detect::Detector::detect($line);
chomp $enc;
if ($enc) {
print "$enc\n";
}
}
答案 0 :(得分:13)
您已设置输入文件句柄的编码(顺便说一句,应该是<:encoding(utf8)
- 请注意冒号)但您尚未指定输出的编码 channel,因此Perl会将未编码的字符值发送到输出
适合单个字节的字符的Unicode值 - 介于0和0x7F之间的基本拉丁语(ASCII),以及0x80和0xFF之间的Latin-1补充 - 非常类似于Windows代码页1252.特别是带有diaresis的小写字母u在Unicode和CP1252中均为0xFC,因此如果输出未编码,则文本将看起来像CP1252,而不是以UTF-8编码的相同代码点的双字节序列0xC3 0xBC
如果您在STDOUT上使用binmode
来设置编码,那么数据将正确输出,但最简单的方法是使用open
pragma这样的
use open qw/ :std :encoding(utf-8) /;
将设置STDIN,STDOUT和STDERR的编码,以及任何新打开的文件句柄。这意味着您不必在打开CSV文件时指定它,并且您的代码将如下所示
请注意,我还添加了use strict
和use warnings
,这些在任何Perl程序中都是必不可少的。我也有
使用autodie
来消除检查所有IO操作状态的需要,并且我利用Perl在双引号内插入数组的方式,在元素之间放置一个空格,这样就不需要{{1调用
join