# CSV教材

1. CSV形式について
2. CSVの構造について
3. CSVライブラリについて
4. Hashをもっと深く知ろう！
5. CSV.readを使ったプログラムを書いてみよう！
6. 番外編：CSVファイルへの「書き込み」

## CSV形式について

CSV形式とはあらゆる種類のソフトウェアで読み書きできる「表形式」で表現できるデータのことです。

> 漢字氏名 | カタカナ氏名 | 電話番号 | メイルアドレス | 住所

表の中の各項目が揃った一単位のデータのことをレコードと言います。
上の表では外枠を指します。
レコードの中にある一つ一つの項目のことをフィールドと言います。
上の表では内枠を指します。

表計算ソフトなどでは1レコードを1行に、 1フィールドを1セルに書き込んで表現します。
表計算ソフトなどでデータの集合を保存するときはそのソフト固有の保存形式で記録しているため、その保存形式に対応したソフトを使わない限り開くことができません。
しかしCSV形式はあらゆる種類のソフトウェアで読み書きできる形式です。

csvファイルを作るときは
ファイル名.csvという形で作ります。

## CSVの構造について

CSV形式は複数のフィールドをフィールドごとにカンマ（,）で区切り、 １レコードを１行におさめたテキストファイル形式となっています。

### 使うときのルール

1. 数値はそのまま書く
2. 文字列はそのまま、もしくはダブルクォート（”）で囲む

### 例として

- Hello(文字列)
- １２３(整数)
- ４５６（文字列）
- Hello,World(文字列)

という内容のCSVファイルを作るときに Hello,123,”456”,”Hello, World” と表します。
この場合Hello,Worldにカンマがついています。
空白文字かカンマがある場合必ずダブルクォートで括りましょう。

He said “Hello”.という文にはダブルクォート（”）が入っています。
この文を入れてCSVファイルを作るときは ”He said ””Hello””.”と表します。
このように文字列自身にダブルクォートが含まれるときはダブルクォートを重ねて表します。

### 例

> 名前 | 電話番号 | 住所 | 職業
> --- | --- | --- | ---
> 公益太郎 | 000-0000-0000 | 山形県 | 学生

名前,電話番号,住所,職業
酒田太郎,000-000-000,山形県,学生

## CSVライブラリについて

CSVライブラリとはRubyで使えるCSVファイルを使ってあらゆることを行えるようにする便利道具のようなものです。
CSVファイルの「読み込み」「書き込み」「１行変換」「全データの繰り返し処理」などを行えます。

### CSVファイルの読み込み①

CSV ファイルからデータを読むには CSV.read メソッドを使います。

#### 使い方

data(変数) = CSV.read(csvファイル名)

これを使うとdataという変数に各行の各フィールドごとに配列化したものがさらに配列化されて入る。

建物名,住所,電話番号
羽黒山 五重塔,山形県鶴岡市羽黒町手向,000-000-000
加茂水族館,山形県鶴岡市今泉字大久保,999-999-999

↓このようなCSVファイルをCSV.readで読み込むと配列の配列が返る

[["建物名", "住所", "電話番号"],
["羽黒山 五重塔", "山形県鶴岡市羽黒町手向", "000-000-000"],
["加茂水族館", "山形県鶴岡市今泉字大久保", "999-999-999"]]

### CSVファイルの読み込み②

CSV.readを使うときはCSV ファイルの1行目の見出しを キーとして値を取り出せる形式で読んだ方が使いやすい。

キーとして値を取り出すとは？

連想配列名 = {キー名1 => バリュー1, キー名2 => バリュー2, キー名3 => バリュー3}

配列に似ているが配列が要素を指定するのに「0」から始まる添字を使用するのに対し、
添字に「キー」と呼ばれる任意の文字列を指定して「バリュー」と呼ばれる要素を指定する。

このようなものをHashと言います。

## Hashをもっと深く知ろう！

### Hashの例

menu = {
"そば" => "300円",
"ケーキ" => "500円",
"ハンバーグ" => "800円"
}
print menu["そば”]
lunch = "ハンバーグ"
print menu[lunch]

出力結果

300円
800円

このように、Hashでは添字が番号ではなく指定したキーとなっている。
要素を取得する際も、キーを指定することでセットになっている値(バリュー)を取得する。

#### ▶CSV.readでCSVファイルを読み込むときは青い部分を付け足すことでHash化させることができる

data = CSV.read("shonai.csv", :headers => true)

そばは300円である。」というように「そば」と「300円」という２つの言葉が関連付いているときにHashを使うととても便利。

## CSV.readを使ったプログラムを書いてみよう！

今回作るのはCSV.readを使った観光スポットを検索するプログラムです。

今回使うファイルはshonai.csvとkankou.rbです。

### shonai.csv

建物名,住所,特徴
羽黒山 五重塔,山形県鶴岡市羽黒町手向,羽黒山参道、東北北地方では最古の塔といわれている。,
白山島,山形県鶴岡市由良2丁目,"由良海岸のシンボルである島。",
加茂水族館,山形県鶴岡市今泉字大久保657-1,約1万のミズクラゲがいる「クラゲドリームシアター」がある。,
庄内観光物産館 ふるさと本舗,山形県鶴岡市布目字中通80-1,庄内地方をはじめとするお土産を数多く取り揃えている。,
酒田米菓（オランダせんべいFACTORY）,山形県酒田市両羽町2-24,オランダせんべいＦＡＣＴＯＲＹではその工程を見学できる。,
丸池様,山形県飽海郡遊佐町直世荒川５７,水深3.5メートル、湧き水だけで満たされた池。,
山居倉庫,山形県酒田市山居町1-1-20,庄内のシンボルである山居倉庫。,
道の駅「とざわ」高麗館,山形県最上郡戸沢村蔵岡黒淵3008-1,韓国風の外観が特徴の戸沢村にある道の駅。,

このcsvファイルを読み込んで取り出していくプログラムを書いていく。

### kankou.rb

          require 'csv'# CSVライブラリ読み込み
            data = CSV.read("shonai.csv", :headers => true)#観光スポット一覧で使うcsvファイル読み込み

            while true
              puts "1 観光スポット一覧"
              puts "0 終了"
              print "どれかひとつ選んでください => "
              input=gets.to_i

              if input == 0 then #もしinputが0だったとき
                break #終了する
              elsif input == 1 then #もしinputが1だったとき
                #↓行ごとに取り出す
                n = 0
                data.each{|row| # rowには1行ずつ値が入り繰り返される
                  printf("%d: %sとはどんなところ？\n", n+=1, row["建物名"])
                  printf("住所 => %s \n特徴 => %s \n",row["住所"], row["特徴"])
                  print("--------------------------\n") }#仕切りの機能（何個あってもいい）
              else
                print "1/0から選んでください\n"
              end
            end

実際にプログラムを動かしてみてね！どう動いたかな？

## CSVファイルへの書き込み

書き込みにはCSV.openメソッドを使う。

CSV.open(ファイル, モード) do |変数|
:
: (変数 << によってファイルの中に書き込む処理)
:
end

書き込む際は、CSV.open メソッドにファイル書き込みオプション "w" または "a" などを与えて行う。

### 書き込みオプションの主な例

- "r"
  読み込みモードで開く。
- "r+"
  読み書きモードで開く。ファイルを読み込む場合 先頭から読み込み始める。
- "w"
  書き込み(新規作成)モードで開く。既存のファイルは0バイトに クリアされる
- "w+"
  読み書きモードで開く。既存のファイルは0バイトにクリアされる。
- "a"
  書き込みモードで開く。ファイルが既に存在する場合は ファイルの終わりから開始し、なければ新規に作成する。
- "a+"
  読み書きモードで開く。ファイルが既に存在する場合は ファイルの終わりから開始し、なければ新規に作成する。

中身が空のCSVファイル「sample.csv」があったとします。

### そのときこのようなプログラムを書くと...

require 'csv'
CSV.open("sample.csv", "w") do |sample| # csv変数に値を追加すればよい
sample << ["name", "phone-number"] # << で1行ぶんの配列を指定する
sample << ["yamada", "000-0000-0000"]
sample << ["ito", "111-1111-1111"]
sample << ["saito", "222-2222-2222"]
sample << ["sasaki", "333-3333-3333"]
end

name,phone-number
yamada,000-0000-0000
ito,111-1111-1111
saito,222-2222-2222
sasaki,333-3333-3333

### このようにCSVファイルの中に書き込まれる。書き込みの時も数値はそのまま書く。文字列はそのまま、もしくはダブルクォート（”）で囲む

プログラムの解説
1行目: 「csv」ライブラリを指定
2行目: 「csv」ライブラリのopenメソッドで「sample.csv」ファイルを開く
3行目～7行目: CSVデータを書き込み

CSVライブラリを使ってプログラムの幅をどんどん広げていこう！！