Ruby UTF-8 から Shift_JIS(Windows-31j) へ変換するときにエラー
残念ながら、世の中はWindowsを中心に回っているため、CSVをやりとりするときには、文字コードをShiftJISにすることが求められたりします。
RubyプログラムをLinuxで書いていると文字コードは基本的にUTF8になるので、文字コード変換をする必要が出てくるわけですが、kconvやString#encode(Ruby 1.9以降)を使ってSJISに変換する際にエラーを吐かれる文字がいくつかあります。
詳しくは、下記の参考ページに書かれていますが、全角チルダ(ウェーブダッシュ,wave-dash)やハイフン(hyphen)、セントやポンドなどの記号が当てはまります。
文字コードで言うと、U+301C、U+2212、U+00A2、U+00A3、U+00AC、U+2014、U+2016あたりですね。
参考:マニアックなプログラミング備忘録「文字化けについて」
というわけで、文字列をkconvやString#encodeに投げる前に、これらの文字をSJISに変換できるようにするメソッドを作ってみました。
# メソッドの命名難しいorz
String#exchangeでは、「変換したいSJIS非互換文字」と「変換先のSJIS互換文字」の文字コードをそれぞれ"U+XXXX"の形で引数として受け取って、String#to_codeとInteger#chrを用いて文字に変換し、String#gsubでレシーバに含まれる全ての非互換文字を互換文字に置換します。
String#to_codeでは、"U+XXXX"という形の文字コードの16進数部分XXXXを10進数として取り出して返しています。
String#sjisableでは、それぞれの非互換文字を順に置換しているだけです。
実際の使い方としてはこんな感じです。
やっつけですが、動くのでよしとしましょう。
【追記】
String#exchangeはハッシュで と書いたほうがキレイなのか? とも思いましたが、どっちのほうがいいんですかね……。
RubyプログラムをLinuxで書いていると文字コードは基本的にUTF8になるので、文字コード変換をする必要が出てくるわけですが、kconvやString#encode(Ruby 1.9以降)を使ってSJISに変換する際にエラーを吐かれる文字がいくつかあります。
詳しくは、下記の参考ページに書かれていますが、全角チルダ(ウェーブダッシュ,wave-dash)やハイフン(hyphen)、セントやポンドなどの記号が当てはまります。
文字コードで言うと、U+301C、U+2212、U+00A2、U+00A3、U+00AC、U+2014、U+2016あたりですね。
参考:マニアックなプログラミング備忘録「文字化けについて」
というわけで、文字列をkconvやString#encodeに投げる前に、これらの文字をSJISに変換できるようにするメソッドを作ってみました。
# メソッドの命名難しいorz
String#exchangeでは、「変換したいSJIS非互換文字」と「変換先のSJIS互換文字」の文字コードをそれぞれ"U+XXXX"の形で引数として受け取って、String#to_codeとInteger#chrを用いて文字に変換し、String#gsubでレシーバに含まれる全ての非互換文字を互換文字に置換します。
String#to_codeでは、"U+XXXX"という形の文字コードの16進数部分XXXXを10進数として取り出して返しています。
String#sjisableでは、それぞれの非互換文字を順に置換しているだけです。
実際の使い方としてはこんな感じです。
やっつけですが、動くのでよしとしましょう。
【追記】
String#exchangeはハッシュで と書いたほうがキレイなのか? とも思いましたが、どっちのほうがいいんですかね……。