2014年03月24日

最近はWindows環境でもUnicodeファイルを作成できてしまうことが多くなった。 その気はなくともできてしまったらしょうがない。ということで、Perlを使っていじってみたので、ここにまとめておく。いろいろてこずったので、記録に残しておかないともったいない。

WindowsのバージョンはWindows 7 (version 6.1.7601)、Perlはv5.18.2である。 なぜPerlかというと、使い慣れているし(なんせ、Netnewsでshar形式のソースが配布されていた頃からの付き合いだ)、Encodeモジュールがあるので便利だからだ。だいいち、手軽に書けるし。

さて、WindowsはリトルエンディアンのOSなので、Unicodeといっても文字エンコーディングはUTF-16LEである。まずはこれを入出力できなければならない。テキストファイルとは言っても、UTF-16はPerlが想定しているテキストとはほど遠いので、ちょっとした手続きが必要だ。

まずは、入出力をバイナリーモードにする。Windowsはファイル内の改行がCRLF ("\r\n", "\x0d\x0a") なのに対して、Perl内部では改行をLF ("\n", "\x0a") で表現するため、入出力時に変換処理を行っている。これを「CRLF変換」と呼ぶことにする。標準状態ではテキストモードで、CRLF変換が有効になっているので、これを無効にしなければならない。たとえば次のように:


binmode(STDIN);

あるいは、オープン時に次のように指定する:


open($fh, "<:raw", $filename) or die("can't open $filename: $!");

ファイルごとに個別指定するのが嫌なら、最初に宣言しておくこともできる。


use open IO => ":raw";

これは、ファイルの入出力オープン時にデフォルトで":raw"(変換なし)に指定することを意味する。標準入出力はすでにオープンされているので、binmodeで個別に設定する必要がある。なお、IOの代わりにINまたはOUTを指定すれば、入力・出力を別々に指定することもできる。(バイナリーモードにするには":bytes"を指定すればよい、と書いてあるドキュメントもあるが、残念ながら":bytes"だけではCRLF変換を無効にしてくれないのでした。だめだめ。)

実は、入出力時に自動的に文字エンコーディングを変換することも可能で、たとえば次のように指定する:


use open IO => ":encoding(utf-8)";

ならば、":encoding(utf-16)"を指定すればよいかというと、そうは問屋が卸さない。":encoding()"を指定してもCRLF変換は無効にならないので、":raw:encoding(utf-16)"と書く必要があるのでした。 しかも、use open":raw:encoding(utf-16)"を指定すると文句を言うので(2つ以上のレイヤー指定には対応していないらしい)、個別にbinmodeで指定しなければならない:


binmode(STDOUT, ":raw:encoding(utf-16)");

これでおしまいかというと、そんなことは全然なくて、まだまだ先は遠いのでありました。だいたい、この方法は使えないというのが次回の結論なのだから。



(12:00)

トラックバックURL

コメントする

名前
 
  絵文字