• WebCamp_インタビュー
    「自信の持てるスキルを得たい!」内定辞退した女子大生がプログラミングを学習したワケ。
    2018.04.28
  • WebCamp_インタビュー
    【卒業生インタビュー】台湾で月間100万UUの訪日旅行メディアを手掛けるCEOが、プログラミングを学んで得たものとは?
    2018.01.15
  • WebCampPro_インタビュー
    未経験31歳からエンジニア転職を実現【実際に聞いてみた】
    2017.04.01
  • WebCamp_インタビュー
    【WebCamp卒業生インタビュー】1ヶ月でRubyをゼロから学び、Webエンジニアとして転職!
    2018.01.15
  • WebCamp_インタビュー
    “未経験”でもたった1ヶ月で営業からエンジニアとして転職!『WebCamp』受講者インタビュー
    2017.10.04
  • WebCamp_インタビュー
    【WebCamp受講生インタビュー】起業準備中にCEOが気がついたプログラミングスキルの重要性とは?
    2017.12.25
  • WebCamp_インタビュー
    「1カ月頑張ればこの先が見えてくる」地元メディアを立ち上げたママさん
    2017.07.20
  • WebCampPro_インタビュー
    未経験でも寿司職人からWebデザイナーになった!ホスピタリティでスクールを支える宮脇トレーナー
    2017.05.26
  • WebCampPro_インタビュー
    未経験から上京し、エンジニアとしてチームラボグループに転職!【WebCampPro卒業生インタビュー】
    2018.03.10
  • WebCamp_インタビュー
    時間や場所にとらわれず自由に働くために必要なスキルとは?【WebCamp卒業生インタビュー】
    2018.01.26
  • WebCampPro_インタビュー
    自分で稼ぐ力をつけるため、新卒5年目の営業マンがエンジニアに転職!【WebCampPro転職者インタビュー】
    2018.02.02

◆当サイトで人気のプログラミング教室のおすすめランキングはこちら!
プログラミングは独学では非効率で、時間を無駄にするリスクがあります。効率的なカリキュラムで学べるスクールを受講しましょう。

Web Camp【マンツーマンサポート】1ヶ月短期集中でプログラミングを学ぶスクール
1ヶ月通い放題・メンター常駐の教室環境でWebサービス等作りたい方
TechAcademyオンラインで開講しているプログラミングスクール
オンラインでどこでも学べる!/教室に行くのが忙しい人でも安心!
Tech Camp教養としてのITスキルを学べるスクール
Webデザイン/AI(人工知能)/IOS/Androidアプリ制作/VRを学びたい方!
WebCampPro転職保証付き!エンジニアとして転職したい人におすすめ!
未経験からプロのエンジニアを3ヶ月で目指すプログラミングスクールです。
11月生募集中!当社人気の転職保証コース
プログラミング学習から転職成功まで導く、当社人気のWebCamp Proコース。
10月生は満員となっております。11月生募集に向け、お早めの申込みをオススメします。
プログラミング未経験でもエンジニア転職を絶対成功させたい
スキルを身に着けて人生を自ら切り開きたい
上記にあてはまる方は、ぜひご検討ください!

はじめに

CSV(comma-separated values)というのは、文字で構成されているテキストファイル(テキストデータ)です。

ただし、CSVの場合は、データがカンマ「, 」で区切られて列を表し、改行で行を表現している表形式のデータで、ファイルの拡張子が「.csv」になっています。また、1行めに、フィールド名がカンマ区切りで入っているヘッダが含まれている場合もあります。

例えば、次のようなファイルです。

test.csv

name,age,sex,height,weight
ryosuke,21,male,165,65
yuri,22,female,159,45
daiki,24,male,172,68
kei,28,female,163,48

test.csvはデータがカンマ区切りで記載されたテキストファイルで、ファイル拡張子が「.csv」になっていますので、CSVファイルの要件を満たしています。

なお、Rubyでは、テキストファイルの読み書きなどは容易にできるクラスやメソッドが準備されていますので、決まりが分かればCSVデータを解析して扱う(配列に入れたり、ハッシュにしたりなどする)ことはできるでしょう。

しかし、CSVについては、一般的によく使われていることから、Rubyでは安全に扱える専用のクラスが準備されています。

今回は、そんな「CSVクラス」について、詳しく解析していきます。

RubyでCSVファイルを扱う

RubyでCSVを安全に扱うことができるCSVクラスは、残念ながらそのまま何もせずに使えるクラスではありません。

rbファイルの先頭辺りで、以下のようにrequireメソッドを使って読み込む必要があります。

require 'csv'

requireメソッドは、別ファイルに定義されているクラスなどを読み込むメソッドです。そのため、以上の1文を追加することで、CSVクラスを使うことができるようになります。

では、ここからCSVファイルやCSVデータを扱いながら、CSVクラスのメソッドの中で、使用頻度の高いメソッドを紹介していきましよう。

その前に、冒頭で紹介した「test.csv」を、Rubyのプログラムのファイル(.rbファイル)を保存する場所と同じ場所に保存しておいてください。

以降は、test.csvファイルを使って、説明していきます。

CSVを扱うメソッド一覧

CSVデータは前述しているようにCSV形式でファイルに保存されたデータがほとんどです。

そのため、ファイルからの読み込みや書き込みが必要です。また、CSVはデータを表の形式で持っていますので、行ごとや列ごとに処理を行う場合が多いです。CSVクラスには、そういった一見面倒そうな処理を比較的簡単に扱えるメソッドが揃っています。

そんな、CSVを扱う主なメソッドを一覧で紹介しましょう。

メソッド 説明
open ファイルを開く
読み込みモード、新規書き込みモード、追記モード、読み書きモードなどのモードでファイルを開くことができる。
close ファイルを閉じる
<<
add_row
puts
1行書き込む
read CSVファイルの一括読み込み
foreach CSVファイルを1行ごとに読み込んで繰り返す
parse CSV形式の文字列を2次元配列へ変換する
parse_line 1行のCSV形式の文字列を配列へ変換する
to_csv 配列をCSV形式の文字列へ変換する

“未経験”でもたった1ヶ月で営業からエンジニアとして転職!『WebCamp』受講者インタビュー
2017-10-04 10:26
今回の記事では、未経験からWebCampを1ヶ月受講し、その後エンジニアとして転職をした喜田さんにお話を伺いました。 <プロフィール> 喜田 大介 さん (28歳) 大学時代はプ...

ファイルを開いて読み書きする(open、<<、add_row、puts)

CSVファイルを開くメソッドには、以下の2つの構文があります。

CSVオブジェクト = CSV.open(CSVファイル, モード)
CSV.open(CSVファイル, モード) do |ブロック引数|
end

「CSVファイル」には、CSVファイルのフォルダとファイル名を記載します。実行するプログラムファイルからの相対位置を指定できますので、プログラムファイルと同じフォルダにある場合は、ファイル名だけで処理可能です。

「モード」には、ファイルの処理方法に合わせて、以下の6種類のいずれかを指定します。なお、デフォルト値として"r"が設定されています。

モード 内容
r ファイルを読み取りモードで開きます
ファイルがなければエラーが発生します
w ファイルを新規書き込みモードで開きます
ファイルがなければ作成します。すでに存在している場合はファイルを空にして開きます
a ファイルを追加書き込みモードで開きます
ファイルがなければ作成します。すでに存在している場合はそのまま開きます
書き込みの処理を行うと、ファイルの末尾に追記します
r+ ファイルを読み書き両用モードで開きます
ファイルがなければエラーが発生します
書き込み処理を行うと先頭からから書き込みます
w+ ファイルを読み書き両用モードで開きます
ファイルがなければ作成します。すでに存在している場合はファイルを空にして開きます
書き込み処理を行うと先頭からから書き込みます
a+ ファイルを読み書き両用モードで開きます
ファイルがなければ作成します。すでに存在している場合はそのまま開きます
読み込みは先頭から行いますが、書き込みはファイルの末尾に追記します

1つめの構文を使えば、CSVファイルを開いて、そのデータを含んだCSVオブジェクトを取得できます。

CSVオブジェクトはeachメソッドを使って、繰り返し処理の中でデータを1行ずつ取得できますので、そこで必要な処理を行うことになるでしょう。

ブロックを渡す2つめの構文では、ブロック引数にCSVオブジェクトが渡されますので、1行ずつのデータ処理を行うために、ブロックの中でeachメソッドを使った繰り返しが必要になります。

これは、一見面倒に見えますが、CSVファイルを開いてデータを読み込む(書き込む)処理をブロック内に収めるため、「明示的にファイルを閉じる必要がない」という利点があります。

じつは、1つめの構文を使った場合、明示的にファイルを閉じる処理(closeメソッド)を行わなければ、ファイルが開いたままになってしまいます。ファイルを開ける数は限られていますので、一定の間動かすと新たにファイルを開けなくなるなど、解析の困難な不具合を作り出してしまうことになります。
※ただし、1つや2つのファイルを開いているだけでは、プログラム終了時にRubyがファイルを閉じますので、大きな問題には見えません

そのため、明示的にcloseメソッドを呼び出す必要のない2つめの構文の方が、安全なプログラムだと言えるでしょう。

ファイルの読み込み(open)

まず、ファイルの読み込みについて、それぞれの構文の具体例を確認しておきましょう。

csv00-1.rb

require 'csv'

# 1つめの構文で読み込む
csv = CSV.open("test.csv")
csv.each do |row|
    p row
end
csv.close # 必ずファイルを閉じること

puts("--------------------")

# 2つめの構文で読み込む
CSV.open("test.csv") do |csv|
  csv.each do |row|
    p row
  end
end
# ブロックの処理が終わると、自動的にファイルが閉じられる

(結果)

["name", "age", "sex", "height", "weight"]
["ryosuke", "21", "male", "165", "65"]
["yuri", "22", "female", "159", "45"]
["daiki", "24", "male", "172", "68"]
["kei", "28", "female", "163", "48"]
--------------------
["name", "age", "sex", "height", "weight"]
["ryosuke", "21", "male", "165", "65"]
["yuri", "22", "female", "159", "45"]
["daiki", "24", "male", "172", "68"]
["kei", "28", "female", "163", "48"]

openメソッドでファイルを開くことで、ファイルのデータを持ったCSVオブジェクトが取得できます。

そして、CSVオブジェクトのeachメソッドを使って、内部のデータを1行ずつ取り出して処理するわけです。

ヘッダありのデータを扱う

CSV形式のデータは表形式のデータです。つまり、1行めのヘッダは、フィールド名が入っているだけでデータではありません。しかし、csv00-1.rbでは、ヘッダもデータと同じように扱われています。

ヘッダをヘッダとして扱うためには、ファイル読み込み時に、以下のようなオプション設定を行わなければいけません。

open(CSVファイル, モード, headers: true)

オプション設定することで、先頭行がヘッダとして扱われます。また、trueの代わりに、カンマ区切りの文字列を、渡すことで、区切られた文字列をフィールド名としたヘッダとして扱われます。

ヘッダを扱えることのメリットは、戻り値が配列ではなくRowオブジェクトになることです。Rowオブジェクトは、ハッシュと同じく、各要素にフィールド名でアクセスできますので、プログラムの可読性が上がることにつながります。

csv01.rb

require "csv"

# 1行めをヘッダとして扱う
CSV.open("test.csv", headers: true)  do |csv|
  csv.each do |row|
    p row["name"]
  end
end

puts("-------------------")

# ヘッダを追加する
CSV.open("test.csv", headers: "name1,age1,sex1,height1,weight1")  do |csv|
  csv.each do |row|
    p row["name1"]
  end
end

(結果)

"ryosuke"
"yuri"
"daiki"
"kei"
-------------------
"name"
"ryosuke"
"yuri"
"daiki"
"kei"

ファイルの書き込み(<<、add_row、puts)

書き込む場合も、openメソッドでCSVオブジェクトを取得するところまでは同じです。

ただ、書き込む場合は、1行書き込みのメソッドを利用することになります。

1行書き込みのメソッドには、3種類(<<、add_row、puts)ありますが、どれも、引数として1行分のデータが格納された配列を渡します。このとき、要素数が多くても少なくても、エラーが出ることなく1行として追加されますので、確認処理を事前に行うなどしておかなければ、意図しない動作をしてしまう可能性がありますので、気を付けましょう。

では、ファイルを"a"で開いて追記をする例を見てみましょう。

csv02.rb

require 'csv'

data1 = ["hikaru","27","male","161","60"]
data2 = ["kota","28","male","178","69"]

# 1つめの構文で書き込む
csv = CSV.open("test.csv","a")
csv.add_row(data1)  # 1行追加
csv.close # 必ずファイルを閉じること

# 表示して確認する
CSV.open("test.csv") do |csv|
  csv.each do |row|
    p row
  end
end

puts("--------------------")

# 2つめの構文で書き込む
CSV.open("test.csv","a") do |csv|
  csv &lt;&lt; data2  # 1行追加
end
# ブロックの処理が終わると、自動的にファイルが閉じられる

# 表示して確認する
CSV.open("test.csv") do |csv|
  csv.each do |row|
    p row
  end
end

(結果)

["name", "age", "sex", "height", "weight"]
["ryosuke", "21", "male", "165", "65"]
["yuri", "22", "female", "159", "45"]
["daiki", "24", "male", "172", "68"]
["kei", "28", "female", "163", "48"]
["hikaru", "27", "male", "161", "60"]
--------------------
["name", "age", "sex", "height", "weight"]
["ryosuke", "21", "male", "165", "65"]
["yuri", "22", "female", "159", "45"]
["daiki", "24", "male", "172", "68"]
["kei", "28", "female", "163", "48"]
["hikaru", "27", "male", "161", "60"]
["kota", "28", "male", "178", "69"]

なお、読み込み、書き込みともに、1行ごとの配列を扱う点がポイントです。

配列であれば、様々なメソッドがありますので、データを扱うのにとても重宝することでしょう。

コツコツ独学×スクールで実践。未経験からエンジニアに転職!【WebCamp卒業生インタビュー】
2018-03-22 23:28
今回の記事では、独学でPHPを1年半学習し、その後WebCampを受講して未経験からエンジニアへと転職された佐々木さんにお話を伺いました。 <プロフィール> 佐々木 祐樹 さん(2...

CSVファイルからのその他の読み込み(read、foreach)

読み込みについては、openメソッド以外にもメソッドが用意されています。

openメソッドでは、データへのアクセスにどうしてもCSVオブジェクトが必要になっています。

しかし、直接データへアクセスしたいことも少なくないでしょう。

そんなときには、次の読み込み用のメソッドを使う方がシンプルになります。

一括読み込み

配列 = CSV.read(CSVファイル)

1行ずつ読み込み

CSV.foreach(CSVファイル) do |line|
  処理
end

どちらを使ってもCSVオブジェクトを介することなく、まるでファイルから直接配列を読み込んでいるかのように、データを取得できます。なお、readメソッドの戻り値は、行ごとの配列の配列という2次元配列になっていますので、注意しましょう。

csv00-1.rbと同じ処理をこれらのメソッドで実現してみます。

csv00-2.rb

require 'csv'

# readメソッドで読み込む
csv = CSV.read("test.csv")
csv.each do |row|
    p row
end
# closeは不要

puts("--------------------")

# foreachメソッドで読み込む
CSV.foreach("test.csv") do |row|
  p row
end
# closeは不要

結果は、csv00-1.rbと同じになります。
※ただし、csv02.rbを実行したあとの場合は、csv00-1.rbよりも多く表示されます。

readメソッドはcloseメソッドを使用する必要はありませんので、不具合を作るリスクがありません。また、foreachメソッドでは、ブロック引数に1行ごとのデータが格納されていますので、プログラムが格段にシンプルになっています。

なお、readメソッド、foreachメソッドともに、openメソッドと同じくheadersオプションを使うことが可能です。

未経験から上京し、エンジニアとしてチームラボグループに転職!【WebCampPro卒業生インタビュー】
2018-03-10 14:42
今回の記事では、たまたま見たテレビ番組がきっかけでエンジニアに興味を持ち、WebCampProを受講して見事転職を決めた中村さんにインタビューしました。 <プロフィール> 中村 駿...

CSV形式の文字列を扱う

ここまでに紹介したメソッドは、ファイルからCSVデータを取り出して配列の形にする変換処理とも言えます。

つまり、読み込みがCSV形式から配列への変換、書き込みが配列からCSV形式への変換とも解釈できるわけです。

じつは、CSVクラスを使えば、ファイルを介することなく、CSV形式になっている文字列(","と改行で区切られた文字列)と配列の相互変換が可能になっています。

CSV文字列から配列へ(parse、parse_line)

","と改行で区切られた文字列(CSV形式の文字列)を配列へ変換するには、parseメソッドを使います。

CSV.parse(CSV文字列)

文字列に改行が含まれている場合、改行までを1つの要素(CSVデータの1行)として、配列へ変換します。

require "csv"
datas = "name,age,sex\nyamada,23,male\nsakurada,28,male"

p(CSV.parse(datas))

(結果)

[["name", "age", "sex"], ["yamada", "23", "male"], ["sakurada", "28", "male"]]

なお、1行分のCSV形式の文字列でも、parseメソッドは2次元配列を返してきてしまいます。

そのため、1行分のデータだけ変換したい場合は、以下のparse_lineメソッドを使う方が良いでしょう。

CSV.parse_line(CSV文字列)

比較してみましょう。

require "csv"
datas = "ino,30,male"

p(CSV.parse(datas))
p(CSV.parse_line(datas))

(結果)

[["ino", "30", "male"]]
["ino", "30", "male"]

配列をCSV形式にする(generate)

parseメソッドとは逆に、配列からCSV形式の文字列を作りたい場合は、generateメソッドを使います。

CSV.generate(CSV形式の文字列 = "") do |ブロック引数|
end

ブロック引数には、引数で渡された文字列をCSVオブジェクトへ変換したものが格納されます。

戻り値としては、ブロック引数のCSVオブジェクトを文字列に変換したものが返されます。

generateメソッドは、引数に渡した「CSV形式の文字列に対して、配列の形式で追加するとCSV形式の文字列で追加してくれる」メソッドだと解釈した方が分かりやすいかもしれません。

ただ、引数のデフォルト値が空文字列であるため、配列からCSV形式の文字列への変換に使うことができるわけです。

require "csv"

# 単純な変換
csv_string = CSV.generate() do |csv|
  csv &lt;&lt; ["yamada","23","male"]
end
p(csv_string)

puts("-----------------")

# 追加
csv_string = CSV.generate(csv_string) do |csv|
  csv &lt;&lt; ["sakurada","28","male"]
end
p(csv_string)

(結果)

"yamada,23,male\n"
-----------------
"yamada,23,male\nsakurada,28,male\n"

to_csvメソッドなら直感的に

また、to_csvメソッドを使っても変換することができます。(配列から使いますので、CSVクラスのメソッドではありません)

配列.to_csv

簡単な例を使って、動作を確認しておきます。

require "csv"
arr = ["keito","22","male"]

p(arr.to_csv)

(結果)

"keito,22,male\n"

なお、2次元配列には対応していませんので、注意してください。

問題「ハッシュをCSVファイルへ保存」

以下のデータを、headerで定義されたヘッダ付きのCSVファイル(q.csv)として保存してください。

pv = {"Apple juice"=&gt;300, "Lemon juice"=&gt;200, "Strawberry juice"=&gt;400, "Orange juice"=&gt;500, "Lemon cookie"=&gt;150, "Peach juice"=&gt;400}

header = ["Item_name", "price"]

ヒント:ハッシュを配列にするには、to_aメソッドが利用できます。

まとめ

CSVファイルは、表形式のデータをテキストファイルという応用範囲の広いファイル形式で扱うことのできるファイルです。そのため、数多くのソフトウェアやデータベースなどで利用されています。

つまり、CSVファイルを簡単に扱えるCSVクラスを駆使することができれば、Rubyプログラムの応用範囲が格段に広がります。

もちろん、ここで紹介した以外にも、CSVクラスにはメソッドがありますし、応用的な使い方も数多くあります。ぜひ、いろいろと試してみてください。


・CSVはデータがカンマ「, 」で区切られており、ファイルの拡張子が「.csv」になっている(カンマで列、改行で行を表している表形式のデータ)
・CSVクラスを使うには、「require 'csv'」で定義を読み込む必要がある
・CSVクラスのメソッドでCSVファイルを読み書きするときは、1行ごとの配列として扱う
・openメソッドを使った場合、closeしなければいけない(ブロックを渡す場合は除く)
・headersオプションを使うことで、先頭行をフィールド名の書かれたヘッダとして扱い、フィールド名でアクセスできるRowオブジェクトを取得できる
・to_csvメソッドは2次元配列に対応していない

問題の答え

require "csv"

pv = {"Apple juice"=&gt;300, "Lemon juice"=&gt;200, "Strawberry juice"=&gt;400, "Orange juice"=&gt;500, "Lemon cookie"=&gt;150, "Peach juice"=&gt;400}
header = ["Item_name", "price"]

CSV.open("q.csv","w") do |csv|
  csv &lt;&lt; header
  pv.to_a.each do |row|
    csv &lt;&lt; row
  end
end

WebCampOnline プログラミングコースについて

WebCampでは、「どこでも学べる」オンラインコースを開講しています。

初心者・未経験の方でもわずか1ヶ月でプログラミングの基礎を学び、アプリケーション開発をすることができます。

WebCampOnlineが選ばれる3つの理由

1.学習の仕方がわからなくても安心!初心者に寄り添った学習カリキュラム

これから学習を始める初心者の方や、独学で挫折してしまった方に向けて、アプリケーション作成をゴールとする一気通貫したカリキュラムを提供しています。2500名を輩出しているWebCampだからこその教室でのリアルな受講生の声を反映し、オンラインコースでも初心者に寄り添った学習体験をご提供いたします。

2.つまずいたらすぐ解決!プロのエンジニアに質問し放題

プログラミング学習で挫折する理由の多くは「つまずいた時に聞ける人がいない」ことです。オンラインコースでは、現役エンジニアやプロ講師に、すぐにチャットでの質問が可能です。つまずきをすぐに解消できるので、挫折せずに学習を継続することができます

3.1ヶ月間で終わらなくても大丈夫!カリキュラムは"卒業後"も"無料"で利用可能

受講したいけど、仕事が急に忙しくなるかもしれないから受講するか迷っている・・・そんな方も多いのではないでしょうか?ご安心ください。カリキュラムは期間終了後も「無料」で使うことができます。また、しっかり学習時間を確保した方も、振り返って学習することでプログラミングスキルがご自身に馴染んできます。

▼まずは無料でWebデザインのカリキュラムを体験しよう!

【インタビュー】1ヶ月でRubyをゼロから学び、Webエンジニアとして転職!

ブラジルから帰国し技術をつけようとRubyエンジニアを目指してWebCampでRubyを学び、見事Webエンジニアとして転職を果たした田中さんにお話を伺いました。

Rubyの学習がしたい。基礎をしっかりと理解したい

転職のサポートがほしい

と考えている方はぜひお読み下さい。

【WebCamp卒業生インタビュー】1ヶ月でRubyをゼロから学び、Webエンジニアとして転職!
2018-01-15 13:23
今回の記事では、WebCampで1ヶ月間Rubyを学習し、Webエンジニアとして転職した卒業生の田中さんにお話を伺いました。 <プロフィール> 田中 デニス 昭彦さん(...
関連キーワード
Rubyの関連記事
  • 【Ruby入門説明書】rescueについて解説
  • 【Ruby入門説明書】jsonについて解説
  • 【Ruby入門説明書】csvについて解説
  • 【Ruby入門説明書】mapについて解説
  • 【Ruby入門説明書】gemsについて解説
  • 【Ruby入門説明書】ruby sliceについて解説
おすすめの記事