初期投入用のDB登録処理を作成した際、CSVファイルを読み込んでデータを登録するようにしたのですが、1列目に登録していたデータを読み込めない現象が発生しました。
対応方法を調査した時によく見かけたBOMの有無の確認方法が、CSVだとうまく確認できないようなので、備忘として残します。
環境
macOS Big Sur 11.0.1
ruby 2.7.2
現象
以下のような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
列が読み込めなくなる。
category,name
北京料理,北京ダック
北京料理,杏仁豆腐
北京料理,炸醤麺
原因
使用したCSVファイルがUTF-8であり、BOM付きであったため。
BOMが文字として扱われているようで、正常にCSVが読み込めない結果となってしまった。
BOM付きファイルの確認方法
確認方法1
ターミナルより、file
コマンドで確認できる。
ただ、CSVファイルではBOM付きであることを判別できないようなので、確認方法2で確認しています。
$ file sample.txt
sample.txt: ASCII text # BOMなしの場合
$ file sample_bom.txt
sample_bom.txt: UTF-8 Unicode (with BOM) text # BOM付きの場合
$ 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の確認、追加、削除 – おもむくがままに