Programming from 30

自分の備忘録が、誰かの為になれば・・

CSVファイルとRubyの備忘録

最近RubyのコードでCSVファイルを使う事があったのでまとめました!

CSVファイルとは

comma-separated values(略称:CSV)は、いくつかのフィールド(項目)を区切り文字であるカンマ「,」で区切ったテキストデータおよびテキストファイル。拡張子は .csvMIMEタイプは text/csvwiki

例えばこんな感じの中身 diary.csv

id,title,content
1,今日はジム,腕立て伏せと腹筋と、スクワットをしました。
2,今日はスターバックスで勉強,とても混んでいて勉強どころではなかった。
3,美術館で草間彌生展,とても素敵な絵画が多かっった。

1行目がカラムの要素、2行目からid,title,contentという風にカンマで区切られています。

用途は色々だと思いますが、エクセルの表の様にデータをまとめる事ができます。RubyにはCSVファイルを扱うライブラリがあり、とても扱いやすくなっています。その中で、いくつかのコードを忘れない様に書き記します(自分用)!

使用方法

まずはrequire 'csv'を記載

  • 読み込み
require 'csv'
csv  = CSV.read("/path/to/file.csv")
readメソッドで
csv = CSV.read("diary.csv")
=> [["id", "title", "content"],
 ["1", "今日はジム", "腕立て伏せと腹筋と、スクワットをしました。"],
 ["2", "今日はスターバックスで勉強", "とても混んでいて勉強どころではなかった。"],
 ["3", "美術館で草間彌生展", "とても素敵な絵画が多かっった。"]
  • foreachを使って1行ずつ読み込むこともできる
require 'csv'
CSV.foreach("diary.csv") do |row|
  p row
end

["id", "title", "content"]
["1", "今日はジム", "腕立て伏せと腹筋と、スクワットをしました。"]
["2", "今日はスターバックスで勉強", "とても混んでいて勉強どころではなかった。"]
["3", "美術館で草間彌生展", "とても素敵な絵画が多かっった。"]
  • 書き込む時
require 'csv'
CSV.open("dairy.csv", "wb") do |csv|
  csv << ["4", "Yokohama.rbにいく", "プログラミングが好きな人が多かった!"]
  csv << ["5", "ハッカーの映画を見る", "聞いたことのある言語が英語で聞けた!なんか感動!"]
end

<#CSV io_type:File io_path:"diary.csv" encoding:UTF-8 lineno:2 col_sep:"," row_sep:"\n" quote_char:"\"" headers:["4", "Yokohama.rbにいく", "プログラミングが好きな人が多かった!"]>

これでもいける!!

CSV.open("diary.csv", "a") do |csv|
  csv.puts ["6","今日は門前仲町に行きました","行ったらイベントが休みだった!メールで来てた!"]
end

dairy.csvを見ると

id,title,content
1,今日はジム,腕立て伏せと腹筋と、スクワットをしました。
2,今日はスターバックスで勉強,とても混んでいて勉強どころではなかった。
3,美術館で草間彌生展,とても素敵な絵画が多かっった。
4,Yokohama.rbにいく,プログラミングが好きな人が多かった!
5,ハッカーの映画を見る,聞いたことのある言語が英語で聞けた!なんか感動!

4と5がちゃんと増えています。

また面白いと思ったのは、CSV::tableを使って、データベースのテーブルの様に扱うことができる点

require 'csv'

table = CSV.table("diary.csv")
=> #<CSV::Table mode:col_or_row row_count:6> #header含め6行

table.headers
=> [:id, :title, :content] # headerを確認できる
table.class
=> CSV::Table  #インスタンスはcsv.tableクラス
table[0]
=> #<CSV::Row id:1 title:"今日はジム" content:"腕立て伏せと腹筋と、スクワットをしました。">  #インデックスで取得できる
table[1]
=> #<CSV::Row id:2 title:"今日はスターバックスで勉強" content:"とても混んでいて勉強どころではなかった。">
table.first
=> #<CSV::Row id:1 title:"今日はジム" content:"腕立て伏せと腹筋と、スクワットをしました。">
able[:id]
=> [1, 2, 3, 4, 5] #headerでも取得可能
table[:title]
=> ["今日はジム", "今日はスターバックスで勉強", "美術館で草間彌生展", "Yokohama.rbにいく", "ハッカーの映画を見る"]
  • ループでも回せる
table.each do |row|
   puts "#{row[0]} #{row[1]} #{row[2]}"
end
#=>
1 今日はジム 腕立て伏せと腹筋と、スクワットをしました。
2 今日はスターバックスで勉強 とても混んでいて勉強どころではなかった。
3 美術館で草間彌生展 とても素敵な絵画が多かっった。
4 Yokohama.rbにいく プログラミングが好きな人が多かった!
5 ハッカーの映画を見る 聞いたことのある言語が英語で聞けた!なんか感動!
=> #<CSV::Table mode:col_or_row row_count:6>
  • 消したい行がある時
  csv_table = CSV.table("diary.csv", headers: true)
  csv_table.by_row!
  csv_table.delete_if { |row| row.field?("今日はジム") }

結構値の取得方法があり、まさにデータベース!さすがRubyのライブラリですね!