LoginSignup
5
2

More than 3 years have passed since last update.

【ruby】CSVファイル読み込み時に1列目のデータが読み込めない時の対応

Posted at

初期投入用のDB登録処理を作成した際、CSVファイルを読み込んでデータを登録するようにしたのですが、1列目に登録していたデータを読み込めない現象が発生しました。
対応方法を調査した時によく見かけたBOMの有無の確認方法が、CSVだとうまく確認できないようなので、備忘として残します。

環境

macOS Big Sur 11.0.1
ruby 2.7.2

現象

以下のようなCSVファイルを、

food.csv
id,category,name
1,北京料理,北京ダック
2,北京料理,杏仁豆腐
3,北京料理,炸醤麺

以下の処理で読み込ませようとしたとき、1列目であるid列が読み込めず、nilとなってしまう。
※データ取得時にヘッダ名を指定したときのみ。indexで指定すると問題なく登録できる。

require 'csv'

CSV.foreach("food.csv", encoding: 'UTF-8', headers: :first_row) do |row|
  Food.seed(:id) do |s|
    s.id = row['id']             # 登録されたデータが全てnilになる。
    # s.id = row[0]              # ヘッダ名ではなく、indexで指定すると、問題なく登録できる。

    s.name = row['name']         # 問題なし。
    s.category = row['category'] # 問題なし。
  end
end

※仮にID列を削除した場合、今度は1列目となるcategory列が読み込めなくなる。

food.csv
category,name
北京料理,北京ダック
北京料理,杏仁豆腐
北京料理,炸醤麺

原因

使用したCSVファイルがUTF-8であり、BOM付きであったため。
BOMが文字として扱われているようで、正常にCSVが読み込めない結果となってしまった。

BOM付きファイルの確認方法

確認方法1

ターミナルより、fileコマンドで確認できる。
ただ、CSVファイルではBOM付きであることを判別できないようなので、確認方法2で確認しています。

txtの場合
$ file sample.txt
sample.txt: ASCII text    # BOMなしの場合
$ file sample_bom.txt
sample_bom.txt: UTF-8 Unicode (with BOM) text    # BOM付きの場合
csvの場合
$ file food.csv
food.csv: CSV text    # BOM付きの場合(BOMなしでも同じ表示となる)

確認方法2

以下のコマンドをターミナルで実行し、表示されたファイルがBOM付きファイル。
※サブディレクトリ配下のファイルを含め表示されます。

$ find . -name '*.csv' | xargs grep -l ^$'\xef\xbb\xbf'
./food.csv    # BOM付きファイルが表示される。

対応方法

nkfコマンドを使用する。macには標準で入っていないため、インストールする必要あり。

$ brew install nkf

$ nkf --version    # インストールの確認
Network Kanji Filter Version 2.1.5 (2018-12-15) 
Copyright (C) 1987, FUJITSU LTD. (I.Ichikawa).
Copyright (C) 1996-2018, The nkf Project.

以下のコマンドより、BOMなしのファイルへ変換できる。

$ nkf --overwrite --oc=UTF-8 food.csv

これで、1列目のrow['id']を問題なく取得できるようになりました。

参考記事

UTF-8 BOM を確認・追加・削除するコマンド [Linux, macOS 編] | CodeNote
Mac(bash)でBOM付きファイルを抽出しBOMを削除するコマンド | KEYPOINT – キー・ポイント株式会社 開発日誌
UTF-8のBOMの確認、追加、削除 – おもむくがままに

5
2
0

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
5
2