无法使用Text :: CSV_XS Perl模块编写UTF-16LE编码的CSV文件

时间:2014-11-05 18:08:22

标签: perl csv encoding

我想写一个用UTF-16LE编码的CSV文件。 但是,文件中的输出搞砸了。有一些奇怪的中文字母:਍挀攀氀氀㄀⸀㬀挀攀氀氀㄀⸀㈀ഀഀ。

这看起来像这里提到的逐字节问题:Creating UTF-16 newline characters in Python for Windows Notepad

关于Perl和Text :: CSV_XS的其他主题没有帮助。

这是我尝试的方式:

#!perl

use strict;
use warnings;
use utf8;
use Text::CSV_XS;

binmode STDOUT, ":utf8";

my $csv = Text::CSV_XS->new({
    binary => 1,
    sep_char => ";",
    quote_char => undef,
    eol => $/,
});

open my $in, '<:encoding(UTF-16LE)', 'in.csv' or die "in.csv: $!";
open my $out, '>:encoding(UTF-16LE)', 'out.csv' or die "out.csv: $!";

while (my $row = $csv->getline($in)) {
    $_ =~ s/ä/æ/ for @$row; # something will be done to the data...
    $csv->print($out, $row);
}


close $in;
close $out;

in.csv包含一些测试数据,并以UTF-16LE编码:

header1;header2;
cell1.1;cell1.2;
äöü2.1;ab"c2.2;

结果如下:

header1;header2;਍挀攀氀氀㄀⸀㄀㬀挀攀氀氀㄀⸀㈀㬀ഀ
æöü2.1;abc2.2;਍

不能选择切换到UTF-8作为输出格式(工作正常btw)。

那么,如何使用Text :: CSV_XS编写有效的UTF-16LE编码CSV文件?

1 个答案:

答案 0 :(得分:5)

Perl默认在Windows上添加:crlf。在添加:encoding之前,先添加它。

这意味着在读取解码之前和写入编码之后将执行LF⇔CRLF转换。这是倒退。

由于满足以下所有条件,它最终会向后使用UTF-8,因为符合以下所有条件:

  • LF的UTF-8编码与其代码点(0A)相同。
  • CR的UTF-8编码与其代码点(0D)相同。
  • 0A总是指LF,无论它们在文件中的哪个位置。
  • 0D总是指CR,无论它们在文件中的哪个位置。

这些条件都不适用于UTF-16le。

修正:

open(my $fh_in,  '<:raw:encoding(UTF-16LE):crlf', $qfn_in)
open(my $fh_out, '>:raw:encoding(UTF-16LE):crlf', $qfn_out)