ファイル入出力とエンコーディング
Ruby1.8 の文字列はただのバイト列だったが、Ruby1.9 からは、それぞれの文字列がエンコーディングを持っている。
エンコーディングの変換には String#encode を使う。
utf8 = 'Ruby関西' eucjp = utf8.encode(Encoding::EUC_JP) utf8.encoding # => #<Encoding:UTF-8> eucjp.encoding # => #<Encoding:EUC-JP>
ファイルのエンコーディングを指定
スクリプトのエンコーディングと入力ファイルのエンコーディングが一致していなければ、読み込んだ文字列は恐らく文字化けすることになる。
入力ファイルのエンコーディングがあらかじめ分かっているなら、それを指定すればよい。
open(fn, 'r:EUC-JP'){|file| ...
上記は日本語 EUC のファイルから読み込む例。
この場合、読み込んだ文字列のエンコーディングは Encoding::EUC_JP となる。
File#open の第2引数で指定した 'r' はモード。'r' は読み込み、'w' は書き込み、など。
モードにつづく ':エンコーディング名' は外部エンコーディングの指定。
読み込んだ文字列をスクリプトのエンコーディングに変換したいなら、内部エンコーディングも指定すれば可能。
open(fn, "r:EUC-JP:#{__ENCODING__}") {|file| ...
__ENCODING__ はスクリプトのエンコーディング。
File#open に指定するのは、エンコーディングの名前 (Encoding#to_s) らしい。
ファイルのエンコーディングが不定
スクリプト起動時に人がファイルのエンコーディングを指定する場合は、下手な作り込みは不要。
以下スクリプトは与えられたファイルを UTF-8, 日本語 EUC, Windows-31J に変換して出力する。
ARGV.each do |fn| [Encoding::UTF_8, Encoding::EUC_JP, Encoding::CP932].each do |enc| open("#{fn}_#{enc.to_s}_#{Encoding.default_external}_#{Encoding.default_internal}", "w:#{enc}") do |f| f.puts open(fn, &:read) end end end
これを enc.rb という名前で保存した場合、以下のように実行する。
$ ruby -Eeuc-jp enc.rb euc.txt
上の例では ruby の -E オプションでエンコーディングを指定。
すると Encoding.default_external が Encoding::EUC_JP になって、指定がなければ入出力は日本語 EUC になる。*1
あまり使い道なさそうだけど、-Eeuc-jp:euc-jp のように Encoding.default_internal も指定できる。
Encoding.default_external を環境変数で制御することもできる。
$ LANG=ja_JP.UTF-8 ./enc.rb utf.txt $ LANG=ja_JP.EUCJP ./enc.rb euc.txt $ LANG=ja_JP.SJIS ./enc.rb sjis.txt
なんか ja_JP.SJIS は違う気もする ……
*1:ファイルが UTF-8 なら -Eutf-8、ファイルが Windows-31J なら -Ecp932 のように指定。