トップ «前の日記(2014-11-23) 最新 次の日記(2014-11-30)» 編集

日々の破片

Subscribe with livedoor Reader
著作一覧

2014-11-29

_ Rubyが使い物にならないこと

正確には、あまり考えずに使うと実は使えないことがあるということだ。

さて、ゾルタン・コチシュはハンガリーのピアニストだ。

おれのディスクにはゾルタン・コチシュの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
素晴らしい快演。
本日のツッコミ(全1件) [ツッコミを入れる]
_ naruse (2014-11-29 04:42)

まず、最初にruby -vしましょう。<br><br>> ruby -e 'p ARGV' *<br>ここで戻り値のエンコーディングを確認し、SJISであること、つまりこの時点で詰んでいることを確認しましょう。


2003|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|

ジェズイットを見習え