システム開発において、CSVファイルの入出力をするシーンは多々あります。
この記事では、RubyでCSVファイルを出力する方法を解説していきます。
CSVとは?
最初に、CSVとはどんなファイルなのかを説明しておきましょう。
CSVはComma Separated Valueの略で、その名の通り、項目をカンマで区切ったファイルです。データが複数ある場合は、改行して複数行に渡って記述します。
以下は、実際のCSVのサンプルです。
id, name, age
1, 山田, 20
10001, 鈴木, 30
3, 伊藤, 40
このように、CSVは表形式のデータを扱うことができ、項目(列)をカンマ区切り、レコード(行)を改行で区切ったシンプルなデータ形式のファイルです。
Excelなどでも表形式のデータが扱えすが、プログラムから入出力する場合は、CSVのほうが簡単で汎用性も高いため、システム開発の現場ではCSVを入出力するプログラムをよく見かけます。
RubyでCSVファイルを出力
Rubyには、標準で「csvライブラリ」が用意されており、簡単なコードでCSVの入出力ができるようになっています。
CSV出力時に、csvライブラリのopenメソッドを使用し、引数にファイルの出力先と、出力モードを指定します。
そしてopenメソッドで作成したCSV オブジェクトに対し、出力するデータを書き込みます。
require "csv"
CSV.open('Sample.csv','w') do |csv|
csv << ["id","name","age"] ##ヘッダ
csv << ["1","山田","20"] ##データ1行目
csv << ["10001","鈴木","30"] ##データ1行目
end
実行すると、次のようなCSVファイルが出力されます。
id,name,age
1,山田,20
10001,鈴木,30
出力モードについて
CSV.openメソッドの第2引数に指定する出力モードは、次のようなものが指定できます。
w:ファイルを書き込みモードで開きます。ファイルがすでに存在していれば内容が置き換えられます。(上書き)
a:ファイルを書き込みモードで開きます。ファイルがすでに存在していれば末尾に出力されます。(追記)
wb:w指定した時の動作に加え、改行コードのLFをそのままLFとして書き込みます。
出力モードにwやaを指定した時は、改行コードはプラットフォーム依存の改行コードで出力されます。(UNIX、LinuxであればLF、WindowsであればCR+LFとなる)
エンコーディングを指定してCSVを出力
CSVファイルを出力する時に文字エンコーディングを指定する場合は、次のようにopenメソッドの引数に指定します。
エンコーディングの指定を省略した場合は、デフォルトのutf-8″が適用されます。
CSV.open('Sample.csv','w', :encoding => "utf-8")
BOM付きのUnicodeで出力する場合は、次のように記述します。
CSV.open('Sample.csv','w', :encoding => "BOM|utf-8")
`utf-8以外のエンコーディングも指定可能で、例えばshift-jisでCSVを出力する場合は、次のように指定します。
CSV.open('Sample.csv','w', :encoding => "sjis")
内部と外部エンコーディングを両方指定する場合は、<外部エンコーディング>:<内部エンコーディング>のように指定します。
CSV.open('Sample.csv','w', :encoding => "sjis:utf-8")
CSVに限らず、テキストファイルに出力する時には「文字化け」に注意が必要です。
例えば、内部コードがutf-8なのに、sjis:sjisのような指定をしてしまうと、文字化けが発生します。
ファイルを出力するときは、内部コードと外部コードが想定通りか確認をするようにしましょう。
変数にCSVを出力
Rubyのcsvライブラリは、CSVをファイルだけでなく、変数に文字列と出力することも可能です。
変数にCSVを出力するときは、csvライブラリのgenerateメソッドを使用します。
require "csv"
## generateメソッドで変数にCSVを出力
string_csv = CSV.generate do |csv|
csv << ["id","name","age"] ##ヘッダ
csv << ["1","山田","20"] ##データ1行目
csv << ["10001","鈴木","30"] ##データ1行目
end
## 変数に出力されたCSVをコンソールに表示
p string_csv
【実行結果】
-----------------------------------
id,name,age
1,山田,20
10001,鈴木,30
ダブルクォーテーションで文字を囲う
CSVでは数値以外の文字は、“値1″,”値2”のようにダブルクォーテーションで囲むのが一般的です。
Rubyでは、:force_quotesオプションを指定することで、文字をダブルクォーテーションで囲むことができます。
require "csv"
CSV.open('Sample.csv','w', :force_quotes => true) do |csv|
csv << ["id","name","age"] ##ヘッダ
csv << ["1","山田","20"] ##データ1行目
csv << ["10001","鈴木","30"] ##データ1行目
end
上のコードを実行すると、次のCSVファイルが出力されます。
"id","name","age"
"1","螻ア逕ー","20"
"10001","驤エ譛ィ","30"
出力されたファイルを見ると、文字だけでなく数値の値までダブルクォーテーションで囲まれています。
:force_quotesオプションは、数値と文字列すべてをダブルクォーテーションで囲むオプションのため、このような結果になります。
しかし一般的なCSVは、数値はダブルクォーテーションで囲まないこと多いようです。
文字のみダブルクォーテーションで囲む場合は、自前のコードで前後にダブルクォーテーションを付加して出力します。
require "csv"
CSV.open('Sample.csv', 'w', :quote_char => '') do |csv|
csv << ["id","name","age"] ##ヘッダ
csv << [1,'"山田"',20] ##データ1行目
csv << [10001,'"山田"',30] ##データ1行目
end
ダブルクォーテーションを指定した文字列をCSVライブラリに渡すと、そのままでは“””値”””のような文字になってしまうため、:quote_char => ”オプションを指定します。
id,name,age
1,"山田",20
10001,"山田",30
さいごに
RubyでCSVファイルを出力する方法を解説してきました。
Rubyでは、標準のcsvライブラリを使用するとこで、簡単コードがCSVファイルが出力できため、是非試してみましょう。
【関連記事】
▶【Rubyの基礎】配列の検索で使われるfindメソッドの使い方
csvライブラリを使用するための、先頭のrequire “csv”を忘れないようにしましょう。requireの指定がないと、エラーになります。