動かざることバグの如し

近づきたいよ 君の理想に

RubyでCSV扱おうとしたら思ったより融通が利かない

原則

  • RubyデフォルトのCSVライブラリのみで動かす
  • Rubyは2.2

サンプルCSVとして以下を用意

name,kana,pref
"函館","はこだて","北海道"
"五稜郭","ごりょうかく","北海道"
"桔梗","ききょう","北海道"
"大中山","おおなかやま","北海道"
"七飯","ななえ","北海道"
"渡島大野","おしまおおの","北海道"
"仁山","にやま","北海道"
"大沼","おおぬま","北海道"
"大沼公園","おおぬまこうえん","北海道"
"赤井川","あかいがわ","北海道"

読み込み

readを使うと二次元配列で読込される

p CSV.read("data.csv")
[["name", "kana", "pref"], ["函館", "はこだて", "北海道"], ["五稜郭", "ごりょうかく", "北海道"], ["桔梗", "ききょう", "北海道"], ["大中山", "おおなかやま", "北海道"], ["七飯", "ななえ", "北海道"], ["渡島大野", "おしまおおの", "北海道"], ["仁山", "にやま", "北海道"], ["大沼", "おおぬま", "北海道"], ["大沼公園", "おおぬまこうえん", "北海道"], ["赤井川", "あかいがわ", "北海道"]]

eachを使うと一行ごとに配列として取得できる

CSV.foreach("data.csv") do |row|
    p row
end
["name", "kana", "pref"]
["函館", "はこだて", "北海道"]
["五稜郭", "ごりょうかく", "北海道"]
["桔梗", "ききょう", "北海道"]
["大中山", "おおなかやま", "北海道"]
["七飯", "ななえ", "北海道"]
["渡島大野", "おしまおおの", "北海道"]
["仁山", "にやま", "北海道"]
["大沼", "おおぬま", "北海道"]
["大沼公園", "おおぬまこうえん", "北海道"]
["赤井川", "あかいがわ", "北海道"]

CSV.foreachの場合はより詳しいオプションが指定できる

CSV.foreach("data.csv", {skip_blanks: true, header_converters: :symbol, headers: true, converters: :numeric,encoding: "UTF-8", col_sep:",", quote_char: '"'}) do |row|
    p row[:name]
end
["函館", "五稜郭", "桔梗", "大中山", "七飯", "渡島大野", "仁山", "大沼", "大沼公園", "赤井川"]
  • skip_blanks: 空行があった場合に無視
  • header_converters: 通常row["name"]だがシンボル指定してあげるとrow[:name]とできる
  • headers: 1行目を名前として読み込みできる
  • converters: デフォルトだと数字も文字列として扱われるが:numeric:integerと指定すると吉
  • encoding: 言わずもがな
  • col_sep: 言わずもがな
  • quote_char: 言わずもがな

デフォルトオプション値はCSV::DEFAULT_OPTIONSで参照できる

{:col_sep=>",",
 :row_sep=>:auto,
 :quote_char=>"\"",
 :field_size_limit=>nil,
 :converters=>nil,
 :unconverted_fields=>nil,
 :headers=>false,
 :return_headers=>false,
 :header_converters=>nil,
 :skip_blanks=>false,
 :force_quotes=>false,
 :skip_lines=>nil}

ただこれをいちいち指定するのはかったるいよね、って時にCSV.table使うと便利 いい感じにやってくれる

CSV.table('data.csv').each do |row|
    p row[:name]
end

書き込み

これしか見つからかなかった

CSV.open("data.csv", "w") do |row|
    row << ["駒ヶ岳","こまがたけ","北海道"]
    row << ["東山","ひがしやま","北海道"]
end