2012-10-28 77 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