CSVデータファイルに出力するためのクラス。 以下のような特徴を持つ。
C++で実装されており高速に動作する。
項目名行あり/なし、いずれの形式も扱うことができる。
RFC4180にほぼ準拠
一行の項目数は固定であることを前提とする。
* MCMD::Mcsvout::new(arguments){block}
Mcsvoutオブジェクトを生成する。 argumentsに、以下の引数をスペースで区切った文字列として指定する。
o= |
出力ファイル名(String) |
f= |
出力するCSVデータのヘッダー(一行目)の項目名文字列を配列で指定する(String Array)。 |
f=を省略してsize=を指定すれば、項目名なしのCSVを出力する。 |
|
size= |
項目名を出力しない時には、CSV項目の数(Fixnum)を指定する。 |
precision= |
Float型変数の有効桁数を指定する。デフォルトは10桁。 |
C言語の出力書式"%.ng"のnの値。 |
|
100/3に対して有効桁数5桁であれば33.333、2桁であれば33となる。 |
|
bool= |
trueとfalseの出力値をカンマで区切って指定する。デフォルトは"1,0" |
* MCMD::Mcsvout::write(values)
配列(Array)に格納された値をCSVデータとして出力する。 配列に格納できるデータクラスはString, Fixnum, Bignum, Float, nil, true, falseである。 それ以外のクラスは全てnilとして扱われる。 配列のサイズが項目名の数より少い場合はnull値が追加出力される。 配列のサイズが項目名の数より多い場合は、超過分は出力されない。
文字列にカンマが含まれていれば、その値は自動的にダブルクオーテーションで囲われ出力される。 文字列にダブルクオーテーションが含まれていれば、連続する二つのダブルクオーテーションに変換される。
csv=MCMD::Mcsvout.new("i=rsl.csv f=a,b,c"){|csv| csv.write(["1",2,3.4]) csv.write([1,2,3,4,5]) csv.write([1,2]) } # 出力結果(rsl.csv) a,b,c 1,2,3.4 1,2,3 1,2,
csv=MCMD::Mcsvout.new("i=rsl.csv size=3"){|csv| csv.write(["1",2,3.4]) csv.write([true,nil,false]) csv.write(["4\"5","","6,7"]) } # 出力結果(rsl.csv) 1,2,3.4 1,,0 "4""5",,"6,7"
MCMD::Mcsvout.new("i=rsl.csv size=3 precision=3 bools=T,F"){|csv| csv.write([0.123456,123456.0]) # 有効桁数の指定は小数点以下の桁数でないことに注意する csv.write([123456,0]) # 有効桁数の指定はFixnumには影響しない csv.write([true,false]) } # 出力結果(rsl.csv) 0.123,1.23e+05 123456,0 T,F
# dat1.csv 顧客,日付 A,20081201 B,20081002 MCMD::Mcsvin.new("i=dat1.csv -array"){|csvIn| MCMD::Mcsvout.new("i=rsl.csv f=#{csvIn.names.join(",")}){|csvOut| csvIn.each{|val| csvOut.write(val) } } } # rsl.csv 顧客,日付 A,20081201 B,20081002
CSVデータの書き込み処理について、Rubyの拡張ライブラリとして提供されている 各種ライブラリをベンチマークとして処理速度の比較を行う。 ベンチマーク対象は以下の2つのライブラリである。
http://www.gesource.jp/programming/ruby/database/fastercsv.html
http://www.ruby-lang.org/ja/old-man/html/CSV.html
Table 2.3にベンチマークテストの結果を示す。 1万行,10万行,100万行のデータについて書き込み実験を行った。 ただし、実ファイルとしては出力せず、nullデバイス(/dev/null)への書き込みとした。 Figure 2.2には、ベンチマークテストで利用したスクリプトの抜粋が示されている。 McsvoutはC++による実装のため、他の二つのライブラリより高速である。 Rubyネイティブコードによる実装との差があらわれているのであろう。
行数 |
10K |
100K |
1000K |
Mcsvout |
0.0158 |
0.150 |
1.50 |
FasterCSV |
0.232 |
1.90 |
20.0 |
CSV |
0.279 |
2.80 |
27.9 |
require 'rubygems' require 'csv' require 'fastercsv' require 'mtools' require 'benchmark' $data = ["12345678", 10, 1.1, true, nil, false] puts Benchmark.measure{ (0...10).each{|i| # Mcsvoutの場合 MCMD::Mcsvout.new("o=/dev/null size=6){|csv| (0...10000).each{|j| csv.write($data) } } # FasterCSVの場合 FasterCSV.open("/dev/null", 'w'){|csv| (0...10000).each{|j| csv << $data } } # CSVの場合 CSV.open("/dev/null", 'w'){|csv| (0...10000).each{|j| csv << $data } } } }
Mcsvin : CSVデータの読み込み