search
LoginSignup
186
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

updated at

Organization

Ruby CSVを扱うためのメモ

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歳

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

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
What you can do with signing up
186
Help us understand the problem. What are the problem?