IronRuby 1.0 におけるエンコーディングの取り扱いについて その2

前回のエントリについて、NAKAMURAさんかフィードバックをいただきました。「$KCODEとはコマンドライン オプションのことですか」という話で、その通りなんですが、この辺はどうなんでしょうかと個人的には考えていたります。コマンドライン オプション「-Kkcode」というものがあります。これを以下のように設定すると、スクリプトファイルのエンコーディングを変更することができます。

  • -Ks: $KCODE='shift-jis'
  • -Ku: $KCODE='utf-8'

利用するスクリプトに応じて-Kオプションを使い分けるというのもあるでしょうし、オプションを設定しなくても動作するようにするという考え方もありますので、私がどちらの立場が好きかといえば、間違いなく後者なだけです。

前回は文字列のエンコーディングを変換するのにSystem::Text::Encoding.Convertメソッドを使ったわけですが、提供されているライブラリを調べるとIconvが使えました。NKFは移植が完了していませんが、Iconvを使えばエンコーディングの変換は問題なくできます。Iconvを使ったコードを以下に示します。

 # オリジナルの読み込み(UTF-8)
d0 = open("utf8 bom.txt").read
# BOM(0xEF 0xBB 0xBF)を除いた文字列の作成
d1 = d0.slice 3..-1
# ICONVモジュール
require 'iconv'
# エンコーディングをUTF-8からシフトJISに変換
d2 = Iconv.conv('shift-jis', 'utf-8', d1)
puts d2

これでir上は、問題なく表示することができました。System::Console::WriteLineメソッドなどで出力するには、正しいエンコーディングを文字列に持たせてやる必要があります。というのは、上記の変換した結果のEncodingプロパティは、ASCII-8BITになっているからです。

IronRubyのIOクラスのソースコードを調べるとRuby 1.9のexternal_encodingとinternal_encodingを実装しようとしていることがわかりました。この実装は、まだ未完成でexternal_encodingがASCII-8BIT(バイナリ)固定になっています。これが、Fileオブジェクトを使って読み込んだ場合のEncodingプロパティがASCII-8BITになっている理由でした。

また「-1.9」オプションを使用すると、不完全ながらRuby 1.9互換モードになります。この1.9モードであれば、String#encodingプロパティへアクセスできるようになりますし、Encodingクラスも不完全ながら使用できるようになります。これらのことから推測できるように、前回のエントリで使っていたString#Encodingプロパティが1.9互換実装の機能を使うものだということです。

SilverlightでIconvを使用するには、「load_assembly 'IronRuby.Libraries', 'IronRuby.StandardLibrary.Iconv'」を使ってモジュールを読み込みます。load_assemblyメソッドは、IronRuby固有のもです。このメソッドを使用する理由は、iconv.rbというライブラリをSilverlightの実行環境で使えるようになっていないからです。もしろんiconv.rbを使えるようにすれば「require 'iconv'」で構いません。