2013-04-18

ruby1.9でBOM付きutf-8のファイルの内容をShift-JISに変換する

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
utf-8のファイルの中身をShift-JISに変更しようと思ったらエラーが出たのです。

以下のような感じを実行しようとしたら、

aaa = open("aaa.csv").read
p aaa.encode("cp932")

以下のようなエラーが出てしまったのです。
in `encode': U+FEFF from UTF-8 to Windows-31J (Encoding::UndefinedConversionError)


どうやら変更しようとしたファイルは、もBOM付きutf-8というものだったようです。

ちなみにBOMとは、バイト順マーク(Byte Order Mark)というもののようで、文書ファイルの先頭に付ける EF BB BF という3バイトのバイナリデータのことのようです。ファイルの文字コードがUTF-8であることを明示するために付けることもあるようです。


で、エラーを出なくするには、以下のようにすればOKです。

aaa = open("aaa.csv", 'r:BOM|UTF-8').read
p aaa.encode("cp932")

ファイルをopenするときに'r:BOM|UTF-8'をつけるとよいようです。
以下が参考になりました。
http://qiita.com/items/2e2d425e439d4b16a279


他の手段として、以下のようなものもあります。

aaa = open("aaa.csv").read
aaa.gsub!("\xEF\xBB\xBF".force_encoding("UTF-8"), '')
p aaa.encode("cp932")

BOMを削除してしまう方法です。
以下が参考になりました。
http://stackoverflow.com/questions/5011504/is-there-a-way-to-remove-the-bom-from-a-utf-8-encoded-file


他にもBOMを削除する方法として以下のような方法もあるようです。

aaa = open("aaa.csv").read
aaa = aaa.unpack('C*')[3..-1].pack('C*').force_encoding("UTF-8") if aaa.unpack('C*')[0..2].pack('C*') == "\xEF\xBB\xBF"
p aaa.encode("cp932")

以下が参考になりました。
http://favotter.net/status.php?id=14919895861


その他の方法として、以下のようなものもあります。

aaa = open("aaa.csv").read
require 'nkf'
p NKF.nkf("-s",aaa)

encodeを使わないでNKFを使えばBOMを気にしないでよさげです。


なんかBOMってめんどくさいなぁとか思ったのですが、BOM付きutf-8のcsvファイルは文字化けせずにexcelで開くことができるというのも調べていたらわかりました。
utf-8のcsvファイルはexcelでは、すべて文字化けすると思い込んでいました。


コメントを投稿