UTF-16 perl输入输出

时间:2012-10-28 00:27:19

标签: windows perl io cygwin utf-16

我正在编写一个脚本,它将UTF-16编码的文本文件作为输入并输出UTF-16编码的文本文件。

use open "encoding(UTF-16)";

open INPUT, "< input.txt"
   or die "cannot open > input.txt: $!\n";
open(OUTPUT,"> output.txt");

while(<INPUT>) {
   print OUTPUT "$_\n"
}

我们只想说我的程序将所有内容从input.txt写入output.txt。

这在我的cygwin环境中完全正常,它使用“这是为cygwin-thread-multi-64int构建的perl 5,版本14,颠覆2(v5.14.2)”

但在我的Windows环境中,正在使用“这是为MSWin32-x64多线程构建的perl 5,版本12,颠覆3(v5.12.3)”,

output.txt中的每一行都预设了除第一行以外的疯狂符号。

例如:

<FIRST LINE OF TEXT>
਀    ㈀  ㄀Ⰰ ㈀Ⰰ 嘀愀 ㌀ 䌀栀椀愀 䐀⸀⸀⸀  儀甀愀渀最 䠀ഊ<SECOND LINE OF TEXT>
...

任何人都可以透露一下为什么它可以在cygwin上工作但不能在windows上工作吗?

编辑:按照建议打印编码图层。

在Windows环境中:

unix
crlf
encoding(UTF-16)
utf8
unix
crlf
encoding(UTF-16)
utf8

在Cygwin环境中:

unix
perlio
encoding(UTF-16)
utf8
unix
perlio
encoding(UTF-16)
utf8

唯一的区别在于perlio和crlf层。

2 个答案:

答案 0 :(得分:5)

[我打算等一下,给出一个彻底的答案,但如果我给你一个快速回答而不是什么,那可能会更好。 ]

问题是crlfencoding图层的顺序错误。不是你的错。

例如,假设你使用UTF-16le print "a\nb\nc\n";(因为它更简单,它可能是你真正想要的)。你最终得到了

61 00 0D 0A 00 62 00 0D 0A 00 63 00 0D 0A 00

而不是

61 00 0D 00 0A 00 62 00 0D 00 0A 00 63 00 0D 00 0A 00

我认为您无法使用open编译语或binmode获得正确的结果,但可以使用open完成。

open(my $fh, '<:raw:encoding(UTF-16):crlf', $qfn)

您需要附加:utf8一些旧版本IIRC。

它适用于cygwin,因为crlf图层仅在Windows上添加。你在那里

61 00 0A 00 62 00 0A 00 63 00 0A 00

答案 1 :(得分:4)

您的编码中有拼写错误。它应该是use open ":encoding(UTF-16)"注意冒号。我不知道为什么它可以在Cygwin上运行而不是Windows,但也可能是5.12对5.14的东西。 Perl似乎可以弥补它,但它可能是造成你问题的原因。

如果不这样做,请检查编码是否应用于文件句柄。

print map { "$_\n" } PerlIO::get_layers(*INPUT);
print map { "$_\n" } PerlIO::get_layers(*OUTPUT);

使用词法文件句柄(即open my $fh, "<", $file)。全局文件句柄是全局,因此程序中的其他内容可能会干扰它们。

如果完成所有检查,如果词法文件句柄正在应用encoding(UTF-16),请告诉我们,我们可以尝试其他方法。

更新:This may provide your answer:“ BOM ed UTF文件不适合流媒体模型,而且必须将它们作为二进制文件进行混淆。”看起来你必须以二进制形式读取文件并将编码作为字符串进行。这可能是5.14中修复的错误。

更新2:是的,我可以确认这是a bug that was fixed in 5.14