perl - 如何从 Text::CSV utf8 输出?

标签 perl csv encoding utf-8

我有一个 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 中的输出文本?

注释:

  1. 环境:openSUSE 13.2 x86_64、perl 5.20.1
  2. 我不使用 Text::CSV::Encoded,因为安装失败。 (因为test.csv是用UTF-8转换的,所以使用Text::CSV::Encoded很奇怪。)
  3. 我使用以下脚本来检查编码。 (我还用它来找出初始 CSV 文件 win.csv 的编码。)

.

#!/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";
  }
}

最佳答案

您已经设置了输入文件句柄的编码(顺便说一句,应该是 <:encoding(utf8) -- 注意冒号),但您尚未指定输出 channel 的编码,因此 Perl 会将未编码的字符值发送到输出

适合单个字节的字符的 Unicode 值 - 0 到 0x7F 之间的基本拉丁语 (ASCII) 和 0x80 到 0xFF 之间的 Latin-1 补充 - 与 Windows 代码页 1252 非常相似。带分号的小写字母 u 在 Unicode 和 CP1252 中都是 0xFC,因此如果未编码输出,文本将看起来像 CP1252,而不是与 UTF-8 编码的相同代码点的两字节序列 0xC3 0xBC

如果您使用binmode在 STDOUT 上设置编码,然后数据将正确输出,但最简单的是使用 open像这样的编译指示

use open qw/ :std :encoding(utf-8) /;

它将设置 STDIN、STDOUT 和 STDERR 以及任何新打开的文件句柄的编码。这意味着您在打开 CSV 文件时不必指定它,您的代码将如下所示

请注意,我还添加了 use strictuse warnings ,这在任何 Perl 程序中都是必不可少的。我也有 使用过autodie为了消除对所有 IO 操作状态进行检查的需要,我利用了 Perl 在双引号内插入数组的方式,在元素之间放置一个空格,从而避免了 join 的需要。调用

#!/usr/bin/perl

use utf8;
use strict;
use warnings 'all';
use open qw/ :std :encoding(utf-8) /;
use autodie;

use Text::CSV;

my $csv = Text::CSV->new({ binary => 1, sep_char => ';' });

open my $fh, '<', 'test.csv';

while ( my $row = $csv->getline($fh) ) {
    print "@$row\n";
}

close $fh;

关于perl - 如何从 Text::CSV utf8 输出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30549164/

相关文章:

python - 使用 Python 将 XML 转为 CSV

java - jsp中的表单返回windows-1252中的文本

css - 在 doctype 之前输出 var_dump 时,Fontello 图标字体显示奇怪的字符,直到清除缓存

.net - 将字符串转换为字节数组时,我如何知道使用什么编码方案?

perl - 如何将 Perl 代码从 mod_perl 移植到 FastCGI?

perl - 为什么 '0'在Perl中为假?

perl - 无法使用 Win32::Console 将 0 作为密码输入

python - 在 Python 中汇总 CSV 行

file - 在 Go 中跳转到文件中的特定行

perl - 如何在 Perl 中检测散列中的空字段?