LoginSignup
28
24

More than 3 years have passed since last update.

RubyでBOM付きUTF-8、BOM無しUTF-8、Shift JISなCSVファイルをそれぞれいい感じに読み込む

Last updated at Posted at 2019-05-30

エンタープライズ寄りなアプリケーションを作っていると、データベースの内容をCSVファイルとしてエクスポートしお客さんに編集してもらい、再度インポートするという処理を書く時がある。

この時、お客さんから我々のアプリケーションに送られてくるCSVファイルの文字コードは、以下の3パターンが考えられると思う。

  • BOM付きUTF-8
    • お客さんがCSVファイルをExcel上で編集し、そのまま上書き保存したもの。
  • BOM無しUTF-8
    • お客さんがCSVファイルを保存時にBOMを削除してくるソフトウェア1上で編集し、上書き保存したもの。
  • Shift JIS
    • お客さんがCSVファイルをExcelブック(xlsxファイル)として保存した後、CSVファイルとしてエクスポートしたもの。

これら3パターンをいい感じに扱うコードがこちらだ。

require 'nkf'

# 文字コード検証部分
headers_str = params["csv"]["tempfile"].readline # 1行目のヘッダ部分だけ取得
encoding = NKF.guess(headers_str) # NKFモジュールで文字コードの判定
encoding = "BOM|#{encoding}" if encoding == Encoding::UTF_8 # UTF-8なら、 BOM| をつける。

# CSVファイル読み込み部分
CSV.foreach(params["csv"]["tempfile"], encoding: encoding).each do |row|
  # 何らかの処理
end

以下にポイントだけ書いておく。

  • NKF.guessEncoding オブジェクトを返す。
  • RubyのNKFモジュールはBOM付きUTF-8とBOM無しUTF-8を区別してくれないようなので、NKF.guessの返り値がUTF-8な時は一律で BOM| をつけている。
    • CSV.foreachのencodingオプションに 'BOM|UTF-8' を渡すとBOMがある場合は自動的に取り除いてくれるので、BOM無しUTF-8文字列を渡しても問題ない
    • BOM|Shift_JIS のような文字列を渡してしまうと問題なので、 if encoding.to_s == "UTF-8" という条件を付けている。

「こんなCSVが送られてきたらダメでしょ!」など、なにかツッコミあったらやさしく教えてください。


  1. そんなものあるのか?未検証。 

28
24
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
28
24