Help us understand the problem. What is going on with this article?

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

エンタープライズ寄りなアプリケーションを作っていると、データベースの内容を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. そんなものあるのか?未検証。 

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away