4

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-thread-multi-64int 用に構築された perl 5、バージョン 14、サブバージョン 2 (v5.14.2) です」を使用している私の cygwin 環境では完全に機能します。

しかし、「これはMSWin32-x64-multi-thread用に構築されたperl 5、バージョン12、サブバージョン3(v5.12.3)です」を使用している私のWindows環境では、

output.txt のすべての行には、最初の行を除いてクレイジーな記号が付加されています。

例えば:

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

Windowsではなく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 層の間です。

4

2 に答える 2

5

[ 待ってしっかり答えようと思ってたけど、何もしないよりは早く答えたほうがいいよ。]

問題はcrlfencodingレイヤーの順序が間違っていることです。あなたのせいではありません。

たとえば、print "a\nb\nc\n";UTF-16le を使用しているとします (その方が単純であり、おそらく実際に必要なものであるからです)。あなたはで終わるだろう

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を追加する必要があります。

crlf層は Windows でのみ追加されるため、cygwinで動作します。そこにあなたが得るだろう

61 00 0A 00 62 00 0A 00 63 00 0A 00
于 2012-10-28T07:00:41.537 に答える
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ファイルハンドルはグローバルであるため、プログラム内の他の何かがそれらを妨害している可能性があります。

すべてがチェックアウトされ、字句ファイルハンドルがencoding(UTF-16)適用されている場合は、お知らせください。別のことを試すことができます。

更新: これはあなたの答えを提供するかもしれません: " BOM ed UTFファイルはストリーミングモデルには適していないので、代わりにバイナリファイルとして丸呑みする必要があります。 "ファイルをバイナリとして読み取り、文字列としてエンコードする必要があるようです。これは5.14で修正されたバグである可能性があります。

更新2:はい、これは5.14で修正されたバグであることを確認できます。

于 2012-10-28T00:54:02.183 に答える