第4回 YokohamaRuby その3

その1その2からの続きです。

後半戦は、@dan5yaさんが「何か質問ないですか?」と仰ってくれたので、1.9になってから出てきたエンコード周りの話について聞いてみた。「初めてのRuby」では「4.10 Ruby 1.9とマルチバイト文字列」と「5.5 エンコーディング」の部分。

文字コードって、普通に出力できたら「あったりまえやん!」って思って、文字化けしたときに初めて慌てるってシロモノなので、ほんとうに困るまで放置する傾向があるんだよね。で、ドツボにはまると。ドツボにはまる前にお勉強しようと思い聞いてみました。

横浜Rubyの場では例5-13と例5-14のコーディングで終わってしまったのでおうちに帰って再整理。

まず、スクリプト自身のエンコード。これはマジックコメントで指定する。先頭にあるこんな感じのやつ。

# -*- coding: utf-8 -*-

このマジックコメントはソースコード上にあるリテラル文字コード情報となる。

次に、外部エンコードと内部エンコード。外部エンコードはファイルを読み書きするときにその対象のファイルの文字コードと思っておけばよい。一方で内部エンコードRubyで処理するためのエンコード。ファイル読み込み時に外部のエンコードから変換先の文字コードを指定する。

と、だらだら書いてもしょうがないのでとりあえずテスト。事前にUTF16BEでファイルを作っておいて(utf16be_japanese.txtって名前)、次のコードを書いてみた。

#!/opt/local/bin/ruby
# -*- coding: utf-8-hfs -*-

File.open("utf16be_japanese.txt","r:UTF-16BE:UTF-8") do |f|
   p f.read
end

外部エンコードをUTF-16BEと指定、内部エンコードUTF-8と指定。スクリプトエンコードutf-8と指定(Macだとutf-8-hfsってものが標準っぽい)。

これをRuby1.9で実行すると、

mba.local{miyohide}% ruby1.9 ex_05_13.rb
"UTF16BEにて日本語を記載しています。\n"

と出力される。ちゃんとUTF16BEで書かれたものをUTF8に変換されていることが確認できる。

ここでこの文字コードを指定しなかったものを用意してみる。

#!/opt/local/bin/ruby
# -*- coding: utf-8-hfs -*-

File.open("utf16be_japanese.txt") do |f|
   p f.read
end

で、同じように実行してみる。

mba.local{miyohide}% ruby1.9 ex_05_13.rb
"\u0000U\u0000T\u0000F\u00001\u00006\u0000B\u0000E0k0fe\xE5g,\x8A\x9E0\x92\x8A\u0018\x8F\t0W0f0D0~0Y0\u0002\u0000\n"

文字化けしているね。これじゃイケテナイ。

ちなみに、内部エンコードを指定しない場合をテストしてみる。

#!/opt/local/bin/ruby
# -*- coding: utf-8-hfs -*-

File.open("utf16be_japanese.txt", "r:UTF-16BE") do |f|
   p f.read
end

結果はちょっと想像してなかったもの。

mba.local{miyohide}% ruby1.9 ex_05_13.rb
ex_05_13.rb:4:in `initialize': ASCII incompatible encoding needs binmode (ArgumentError)
	from ex_05_13.rb:4:in `open'
	from ex_05_13.rb:4:in `<main>'
mba.local{miyohide}%  

UTF-16BEはASCII非互換なので、読み込むときはバイナリモードにせんとあかんよってことかな。というわけで、次のようにバイナリモードにしてみた。

#!/opt/local/bin/ruby
# -*- coding: utf-8-hfs -*-

File.open("utf16be_japanese.txt", "rb:UTF-16BE") do |f|
   p f.read
end

分かりにくいだろうけど、"r:UTF-16BE"って書いているところにbを付け足して"rb:UTF-16BE"にした。で、実行すると、

mba.local{miyohide}% ruby1.9 ex_05_13.rb
"UTF16BE\u306B\u3066\u65E5\u672C\u8A9E\u3092\u8A18\u8F09\u3057\u3066\u3044\u307E\u3059\u3002\n"
mba.local{miyohide}%

文字化けはしているけど、最初のUTF16BEは出ているし、UTFのコード値であることが微妙に分かる感じ。

結局、なんとなぁくわかった感じになったイメージ。もうちょっと自分で色々いじってみたらもっと分かってくるかなぁと思う。

最後は懇親会と忘年会編で。