在Perl中使用Unicode进行CRLF转换

egdjgwm8  于 2022-11-15  发布在  Perl
关注(0)|答案(3)|浏览(165)

我尝试在Windows上用Perl写入Unicode(UCS-2 Little Endian)文件,如下所示。

open my $f, ">$fName" or die "can't write $fName\n";
binmode $f, ':raw:encoding(UCS-2LE)';
print $f, "ohai\ni can haz unicodez?\nkthxbye\n";
close $f;

它基本上可以工作,只是我不再像在普通文本文件中那样在输出中得到LF -〉CR/LF的自动转换。(输出文件只有LF)如果我在“binmode”调用中省略了:raw或add:crlf,那么输出文件就会变成乱码。我试过重新排序“directives”(即:encoding before:raw),但无法使其工作。同样的问题也存在于阅读中。

lbsnaicq

lbsnaicq1#

这对我在windows上很有效:

open my $f, ">:encoding(UCS-2LE):crlf", "test.txt";
print $f "ohai\ni can haz unicodez?\nkthxbye\n";
close $f;

在test.txt中生成UCS-16 LE输出

ohai
i can haz unicodez?
kthxbye
wnrlj8wa

wnrlj8wa2#

下面是我发现的工作方式,至少在perl5.10.1中是这样的:
输入:

open(my $f_in, '<:raw:perlio:via(File::BOM):crlf', $file);

输出量:

open(my $f_out, '>:raw:perlio:encoding(UTF-16LE):crlf:via(File::BOM)', $file);

它们透明地处理BOM、CRLF转换和UTF-16 LE编码/解码。
请注意,根据perlmonks下面的帖子,如果尝试使用binmode()而不是open()指定,则需要额外的“:pop”:

binmode $f_out, ':raw:pop:perlio:encoding(UTF-16LE):crlf';

这也是我的经验所证实的。但是,我无法让这个与“:via(File::BOM)”层一起工作。
参考文献:
http://www.perlmonks.org/?node_id=608532
http://metacpan.org/pod/File::BOM

khbbv19g

khbbv19g3#

:crlf层在输出流中进行0x 0A-〉0x 0 D 0x 0A(\n --> \r\n)的简单字节Map,但在大多数情况下,这在任何宽字符编码中都无效。
使用原始模式但显式打印CR怎么样?

print $f "ohai\r\ni can haz unicodez?\r\nkthxbye\r\n";

或者,如果需要考虑可移植性,请找出并明确使用正确的行尾:

## never mind - $/ doesn't work
# print $f "ohai$/i can haz unicodez?$/kthxbye$/";

open DUMMY, '>', 'dummy'; print DUMMY "\n"; close DUMMY;
open DUMMY, '<:raw', 'dummy'; $EOL = <DUMMY>; close DUMMY;
unlink 'dummy';

...

print $f "ohai${EOL}i can haz unicodez?${EOL}kthxbye${EOL}";

与这个问题无关,但Ωmega在一条评论中提到了:raw:bytes之间的区别。正如perldoc perlio中所述,可以将:raw视为删除所有I/O层,将:bytes视为删除一个:utf8层。比较这两个命令的输出:

$ perl -E 'binmode *STDOUT,":crlf:raw"; say' | od -c
0000000  \n
0000001

$ perl -E 'binmode *STDOUT,":crlf:bytes";say' | od -c
0000000  \r  \n
0000002

相关问题