行動すれば次の現実

テック中心の個人ブログ

CSV.generateでUTF-8からShift−JISに変換したときの文字コード変換エラーを回避する

CSV.generateメソッドでUTF-8の文字列をShift-JISに変換して書き込もうとしたら

U+2613 from UTF-8 to Windows-31J 
incompatible character encodings: UTF-8 and Windows-31J

というエラーが発生しました。

docs.ruby-lang.org

上記リファレンスに記載の通り、そのまま使うと文字コード変換で失敗する可能性があるので、適宜変換などして使う必要があります。

主に機種依存文字などが当てはまりますが、一つ一つ変換処理を定義するのもイタチごっこなので、潔く変換失敗文字列は全無視する方針にしました。

実装

def sjis_safe(str)
  str.encode(Encoding::SJIS, invalid: :replace, undef: :replace)
end
pry(main)> '☓ほげほげ'.encode(Encoding::SJIS, invalid: :replace, undef: :replace).encode(Encoding::UTF_8)
=> "?ほげほげ"

使用例

CSV.generateでAppendしていく直前にsjis_safeで変換するイメージです。

csv_string = CSV.generate(encoding: Encoding::SJIS, force_quotes: true) do |csv|
  csv << [
    sjis_safe(name).encode(Encoding::UTF_8)
  ]
end

Shift-JISを扱うときはこういう考慮が必然なので早く一掃されてほしいと願います。