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

Ruby CSVを扱うためのメモ

More than 3 years have passed since last update.

Rubyでcsvを扱うときにパッと使えるようにメモを残しておきます。
やることは以下です。

  • CSVファイルからデータを読み込むこと ( CSV.read )
  • 読み込んだCSVデータをtxtファイルに出力すること ( File.open、file.write )

おまけ

  • CSV.foreachでもCSVから読み込み
  • CSV.generateでCSVで出力する

CSV.read

member.csvというcsvファイルを読み込んで、intro.txtとファイルに出力するサンプルです。

create_intro.rb
require 'csv'

csv_data = CSV.read('member.csv', headers: true)
puts "start..."

File.open("intro.txt", 'w') do |file|
  csv_data.each do |data|
    intro_msg = "#{data["club"]}クラブ所属の#{data["age"]}歳、#{data["name"]}です。\n"
    puts intro_msg
    file.write(intro_msg)
  end
end

puts "complete! See intro.txt."
member.csv
id,name,club,age
1,shizuma,baseball,22
2,qiita,soccer,33
3,taro,tennis,16

以下のファイルが出力されるファイルです。

intro.txt
baseballクラブ所属の22歳、shizumaです。
soccerクラブ所属の33歳、qiitaです。
tennisクラブ所属の16歳、taroです。

解説

require 'csv'

csvライブラリを読み込みます。

csv_data = CSV.read('member.csv', headers: true)

readメソッドを使ってCSVのデータを読み込みます。
headersオプションを使うと、CSVの初めの1行はheaderとして出力の際に無視されます。今回はこのオプションを使っていますが、headerがないときはこのオプションはいりません。
ちなみに今回のheaderはcsvファイルの id,name,club,age のことですね。

File.open("intro.txt", 'w') do |file|
  csv_data.each do |data|
    intro_msg = "#{data["club"]}クラブ所属の#{data["age"]}歳、#{data["name"]}です。\n"
    puts intro_msg
    file.write(intro_msg)
  end
end

まず、 File.openの箇所ですが、第一引数に生成したいファイル名、第二引数にオプションをいれています。今回の「w」はファイルを上書きしますが、「a」とするとファイルに追記していきます。

次に、csv_data.each のところですがdataという変数にcsvファイルのデータが1行ずつ入ります。「,」区切りで左から0、1、2、...という番号がつきます。

追記:

intro_msg = "#{data["club"]}クラブ所属の#{data["age"]}歳、#{data["name"]}です。\n"

の箇所ですが、はじめは以下のように左からの順番で値を取得していましたが、 @scivola さんにコメントを頂き上記に変更しました。csvにheaderがある場合はheaderの値で指定出来るのですね。便利です!

intro_msg = "#{data[2]}クラブ所属の#{data[3]}歳、#{data[1]}です。\n"

参考

その他オプション等
class CSV

ついでに色々やってみた

CSV.foreach

readで一気に読み込まなくても、foreachでやれば良さ気ですね。
やってることは上記のreadのファイルと一緒です。便利。

require 'csv'

puts "start..."

File.open("intro.txt", 'w') do |file|
  CSV.foreach('member.csv', headers: true) do |data|
    intro_msg = "#{data["club"]}クラブ所属の#{data["age"]}歳、#{data["name"]}です。\n"
    puts intro_msg
    file.write(intro_msg)
  end
end

puts "complete! See intro.txt."

CSV.generate

CSVで吐き出すことも出来るみたいです。読み込んだデータもCSVですが、少し加工してまたCSVで出力してみます。

require 'csv'

puts "start..."

intro_csv = CSV.generate do |csv|
  CSV.foreach('member.csv', headers: true) do |data|
    intro_msg = [
      data["id"],
      data["name"],
      "#{data["club"]}クラブ",
      "#{data["age"]}歳"
    ]
    csv << intro_msg
    puts intro_msg
  end
end

File.open("intro.csv", 'w') do |file|
  file.write(intro_csv)
end

puts "complete! See intro.csv."

出力は以下のような感じ。

intro.csv
1,shizuma,baseballクラブ,22歳
2,qiita,soccerクラブ,33歳
3,taro,tennisクラブ,16歳

これだけあれば色々出来そうですね!

Why not register and get more from Qiita?
  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
No 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
ユーザーは見つかりませんでした