Perl 在Windows上使用BOM和CRLF行分隔符创建UTF-16LE
我需要在Windows7框中生成一些带有CRLF行分隔符的UTF-16LE编码文件。(目前使用的是草莓5.20.1) 我需要花很长时间才能得到正确的输出,我想知道我的解决方案是否是正确的方法,因为对于Perl中的其他语言来说,它似乎过于复杂了。特别是:Perl 在Windows上使用BOM和CRLF行分隔符创建UTF-16LE,perl,unicode,newline,utf-16,byte-order-mark,Perl,Unicode,Newline,Utf 16,Byte Order Mark,我需要在Windows7框中生成一些带有CRLF行分隔符的UTF-16LE编码文件。(目前使用的是草莓5.20.1) 我需要花很长时间才能得到正确的输出,我想知道我的解决方案是否是正确的方法,因为对于Perl中的其他语言来说,它似乎过于复杂了。特别是: 为什么Perl使用正确的BOM和编码(UTF-16)生成有效的UTF-16大端码,而如果我使用UTF-16LE或UTF-16BE而不使用额外的包文件::BOM,则没有BOM 为什么CRLF处理看起来像是有问题的(它被输出为0d0a00而不是0d
- 为什么Perl使用正确的BOM和
生成有效的UTF-16大端码,而如果我使用编码(UTF-16)
或UTF-16LE
而不使用额外的包UTF-16BE
,则没有BOM文件::BOM
- 为什么
处理看起来像是有问题的(它被输出为CRLF
而不是0d0a00
),而没有一些过滤器的旋转?我怀疑对于一种有这么多用户的语言来说,这可能是一个真正的bug0d00a00
use strict;
use warnings;
use utf8;
use File::BOM;
use feature 'say';
my $UTF;
my $data = "Hello, héhé, 中文.\nsecond line : my 2€"; # 中文 = zhong wen = chinese
# UTF16 BE + BOM but incorrect CRLF: "0D 0A 00" instead of "0D 00 0A 00"
open $UTF, ">:encoding(UTF-16)", "utf-16-std-be.txt" or die $!;
say $UTF $data;
close $UTF;
# same as UTF-16BE (no BOM, incorrect CRLF)
open $UTF, ">:encoding(ucs2)", "utf-ucs2.txt" or die $!;
say $UTF $data;
close $UTF;
# UTF16 BE, no BOM, incorrect CRLF
open $UTF, ">:encoding(UTF-16BE)", "utf-16-be-nobom.txt" or die $!;
say $UTF $data;
close $UTF;
# UTF16 LE, no BOM, incorrect CRLF
open $UTF, ">:encoding(UTF-16LE)", "utf-16-le-nobom-wrongcrlf.txt" or die $!;
say $UTF $data;
close $UTF;
# UTF16 LE, BOM OK but still incorrect CRLF
open $UTF, ">:encoding(UTF-16LE):via(File::BOM)", "utf-16-le-bom-wrongcrlf.txt" or die $!;
say $UTF $data;
close $UTF;
# UTF16 LE non raw incorrect
# (crlf by default on windows) -> 0A => 0D 0A
open $UTF, ">:encoding(UTF-16LE):via(File::BOM)", "utf-16-le-bom-wrongcrlf2.txt" or die $!;
print $UTF $data, "\x0a"; # 0A is magically expanded to 0D 0A but wrong
close $UTF;
# UTF16 LE + BOM + LF
# raw -> 0A => 0A
# could be correct on UNIX but I need CRLF
open $UTF, ">raw::encoding(UTF-16LE):via(File::BOM)", "utf-16-le-bom-wrongcrlf3.txt" or die $!;
say $UTF $data;
close $UTF;
# manual BOM, but CRLF OK
open $UTF, ">:raw:encoding(UTF-16LE):crlf", "utf-16-le-bommanual-crlfok.txt" or die $!;
print $UTF "\x{FEFF}";
say $UTF $data;
close $UTF;
#auto BOM, CRLF OK ?
#incorrect, says utf8 "\xA9" does not map to Unicode at c:/perl/Dwimperl-5.14/perl/lib/Encode.pm line 176.
# But I cannot see where the A9 comes from ??!
#~ open $UTF, ">:raw:encoding(UTF-16LE):via(File::BOM):crlf", "utf-16-le-autobom-crlfok1.txt" or die $!;
#~ print $UTF $data;
#~ say $UTF $data;
#~ close $UTF;
# WTF? \n becomes 0D 00 0D 0A 00
open $UTF, ">:encoding(UTF-16LE):crlf:via(File::BOM)", "utf-16-le-autobom-crlf2.txt" or die $!;
say $UTF $data;
close $UTF;
#CORRECT WAY?? : Automatic BOM, CRLF is OK
open $UTF, ">:raw:encoding(UTF-16LE):crlf:via(File::BOM)", "utf-16-le-autobom-crlfok3.txt" or die $!;
say $UTF $data;
close $UTF;
手动BOM,但CRLF正常
是的,以下确实是正确的:
:raw:encoding(UTF-16LE):crlf + manual BOM
“清除”现有的:raw
和:crlf
层:encoding
在字节和代码点之间转换:编码
在crlf和LF之间转换:crlf
读取
===================================================>
代码
+------+字节+----+点+----+点+------+
|文件|------------------:enc |------------------:crlf |--------------------代码|
+------++---+CRLF+----+LF+---+
正如我在中引用的博客文章中提到的,在我看来,PERLIO_F_CRLF
不应该设置在Windows上最底层的“unix”层上。至少,我是这样读的:“即使在区分O_文本
和O_二进制
的平台上,这一层总是O_二进制
”@SinanÜnür,:unix
也使用O_二进制
作为perliol文档。不添加:crlf
将使Perl输出对许多程序“不可读”。尝试perl-e“binmode STDOUT;print qq{a\nb\nc\n}>a.txt和记事本a.txt
它也会弄乱几乎所有读取文本文件的perl代码。请注意,“手动BOM”可以打印为“\n{BOM}”
,我认为这比将use File::BOM
和:via(File::BOM)
添加到程序更干净。如果您使用的开放模式仅为UTF-16
,则Encode
将为您添加BOM表,但假定为编码。如果要影响这一假设,真的应该有办法。如果open
pragma允许指定多个层,那么可以使用类似:encoding(UTF-16LE):via(File::BOM):crlf
的东西,这也会很好specified@Borodin,应该是:via(File::BOM,UTF-16le):crlf
(即UTF-16le
应该是BOM处理程序的参数),虽然:via
目前可能不支持该语法。您用正确的方式标记的方法是什么?是推荐的方法,但正如我对ikegami的回答所评论的,我的首选是在打开文件后立即显式打印BOM。您可以通过Unicode名称指定字符,而不是依赖“幻数”FEFF,如print$UTF“\N{BOM}”
Read
===================================================>
Code Code
+------+ bytes +------+ Points +-------+ Points +------+
| File |-----------| :enc |------------| :crlf |------------| Code |
+------+ +------+ CRLF +-------+ LF +------+
<===================================================
Write