著作一覧 |
正確には、あまり考えずに使うと実は使えないことがあるということだ。
さて、ゾルタン・コチシュはハンガリーのピアニストだ。
おれのディスクにはゾルタン・コチシュのMP3(アマゾンで買った)が入っている。
C:\Users\arton\Music\Amazon MP3>dir ドライブ C のボリューム ラベルがありません。 ボリューム シリアル番号は E0D4-CC67 です C:\Users\arton\Music\Amazon MP3 のディレクトリ 2014/10/21 22:22 <DIR> . 2014/10/21 22:22 <DIR> .. (snip) 2014/04/15 20:31 <DIR> Vladimir Krainev, Dmitri Kitaenko & Radio-Si nfonie-Orchester Frankfurt 2014/04/15 20:35 <DIR> Zoltán Kocsis 0 個のファイル 0 バイト
このディレクトリで次のRubyのプログラムを動かしてみよう。
ruby -e 'p ARGV' *
すると次の結果が得られる。
["Allison Cornell", (snip) "Vladimir Krainev, Dmitri Kitaenko & Radio-Sinfonie-Orchester Frankfurt", "Zoltan Kocsis"]
はてZoltanのaの上が少し寂しいようだ。ちゃんと読めているのだろうか?
そこで次のように変えて、最後にあるコチシュのディレクトリをFileとしてみてみよう。
ruby -e 'p ARGV; p File.new(ARGV.last)' *
実行すると
["Allison Cornell", (snip) "Vladimir Krainev, Dmitri Kitaenko & Radio-Sinfonie-Orchester Frankfurt", "Zoltan Kocsis"] -e:1:in `initialize': No such file or directory @ rb_sysopen - Zoltan Kocsis (Er rno::ENOENT) from -e:1:in `new' from -e:1:in `'
本来はErrno::EISDIRになるはず
これは、コマンドラインの取り込みが現在の環境(上だとdirの出力からわかるように、日本語環境(CP932))に基づいて行われているのが原因だ。その結果、ハンガリー語のaの上にアクセンテギュ(ハンガリー語で何と呼ぶかは知らない)が付いた文字はCP932には無いため、ARGV内の文字列に変換する過程で化けてしまう。
解決するには、とりあえずコマンドラインに*を使って取り込むのはあきらめて、プログラム内でutf-8にした*でglobすれば良い。
ruby -e 'a=Dir.glob("*".force_encoding("UTF-8")); p a; File.new(a.last)'
これを実行すると次のように出力される。
["Allison Cornell", (snip) "Vladimir Krainev, Dmitri Kitaenko & Radio-Sinfonie-Orchester Frankfurt", "Zolt\u00E1n Kocsis"] -e:1:in `initialize': Is a directory @ rb_sysopen - Zoltテ。n Kocsis (Errno::EISDI R) from -e:1:in `new' from -e:1:in `'
例外がErrno::EISDIRに変わったことから、正しくファイル名が取れていることがわかる。aの部分は\u00E1としてUnicodeで取り込まれている。
\u00E1がaアクセンテギュかどうかを見るにはpをputsに変えてみる。(-Kuを付ければpのままでも表示される。CP932で動いているためpを使うと表現できない文字はエスケープされたものとして出力されている)
>ruby -e 'a=Dir.glob("*".force_encoding("UTF-8"));puts a;File.new(a.last)' Allison Cornell (snip) Vladimir Krainev, Dmitri Kitaenko & Radio-Sinfonie-Orchester Frankfurt Zoltán Kocsis -e:1:in `initialize': Is a directory @ rb_sysopen - Zoltテ。n Kocsis (Errno::EISDI R) from -e:1:in `new' from -e:1:in `'
と、aアクセンテギュだと確認できる(例外のメッセージもrescueしてエンコードを変えれば正しく表示されるはず――と思ったらバグだったらしい。そのうち直るはず)。
この問題は、現在、どうすれば互換性を維持しつつうまく解決できるかどうか議論されていて、だいたいの方向が決まりつつある。参照:Ruby: IO and Encodings
B00BH9FD46ジェズイットを見習え |
まず、最初にruby -vしましょう。<br><br>> ruby -e 'p ARGV' *<br>ここで戻り値のエンコーディングを確認し、SJISであること、つまりこの時点で詰んでいることを確認しましょう。