2012-10-28 53 views
4

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

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的线程多64int内置的Perl 5,版本14,颠覆2(v5.14.2)”

但在我的Windows环境,它使用“这是perl 5,版本12,为MSWin32-x64-multi-thread构建的subversion 3(v5.12.3)”,

output.txt中的每一行都预先添加了疯狂的符号第一行。

例如:

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

谁能给出为什么它在Cygwin上而不是窗户的一些见解?

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

在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层之间。

+0

也许那些“疯狂的符号”是无论你正在使用查看它们不显示UTF16窗口;) –

+0

我使用记事本+ +显示output.txt的。如果我使用cygwin运行脚本并生成文件,它工作得很好,但当我使用Windows运行脚本时,它也充满了疯狂的符号 – allenylzhou

+0

尝试将Windows Perl升级到5.14或5.16,这将消除这种可能性一个5.12的错误。可以是[Strawberry Perl](http://strawberryperl.com/)或[ActivePerl](http://www.activestate.com/activeperl/downloads)。 – Schwern

回答

3

【我打算等待并给出一个彻底的答案,但是如果我给你一个快速的答案比什么都没有更好。 ]

问题是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) 

您需要在旧版本IIRC上附加:utf8

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

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

我不完全理解这些不同编码层工作的目的。但是这解决了我的问题:打开我的$输出,“>:raw:encoding(UTF-16)”,“output.txt”;追加:crlf似乎没有什么区别(这是令人惊讶的,因为你说问题是由于错误的顺序引起的)。但是预先考虑:raw是必要的(否则也会出现相同的问题) – allenylzhou

+0

有和没有的区别:crlf是所使用的行结束符(CR LF vs LF) – ikegami

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)。 Glob文件句柄为global,因此程序中的其他内容可能会干扰它们。

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

UPDATE:This may provide your answer:“BOM编辑UTF文件不适合流模型,它们必须咕噜咕噜的二进制文件,而不是”看起来,你必须阅读为二进制文件并做编码为串。这可能是5.14版本中的一个错误。

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

+0

正如你所建议的,我添加了冒号,并改为使用词法文件句柄,但它没有效果。请参阅编辑我的问题的打印输出。唯一的区别是在Windows环境中有一个crlf层,在cygwin环境中有一个perlio层。 – allenylzhou

+0

@ aylz5073查看更新。您可能遇到5.12中的UTF-16编码错误。 – Schwern

+0

我刚刚用ActivePerl 5.16试了一下,并没有消除这个问题。我想要做的另一个观察是,如果我将编码从“:encoding(UTF-16)”更改为“:encoding(UTF-16LE)”,那么output.txt会变成某种形式的充满NUL标记的二进制文件只是在我的原始文章中显示的我的文本行中添加了一些奇怪的符号。我想我会尝试在你提供的链接中的解决方案,并让你更新。 – allenylzhou