Ruby で CSV ファイルを扱うには,Ruby の CSV パッケージを使うのが簡単.ファイルサイズが巨大(例えば 100Mバイト以上)で無ければ性能的にも問題ない
このページでは,次のプログラム例を示す.
※ CSV ファイルを insert into 形式の SQL 文に変換するプログラムについては,別ページで説明
次のような CSV ファイルを,ファイル名 hoge.csv で保存 (Store the following file. the file name is 'hoge.csv').
1, 2011, 12, 1, kaneko, orange A, 1.2, 10, 2011-12-01 10:42:48 2, 2011, 12, 1, miyamoto, Apple M, 2.5, 2, 2011-12-01 10:42:59 3, 2011, 12, 3, kaneko, orange B, 1.2, 8, 2011-12-03 11:08:56 4, 2011, 12, 4, miyamoto, Apple L, 3, 1, 2011-12-04 15:35:12
次のような CSV ファイルを,ファイル名 hoge2.csv で保存 (Store the following file. the file name is 'hoge2.csv').
1,100,1,2,3 2,200,hoge,hoge2,hoge3 3,300,"a","b","x" 4,400,"""foo","hoo2"""
次のような CSV ファイルを,ファイル名 hoge3.csv で保存 (Store the following file. the file name is 'hoge3.csv').
id, year, month, day, cname, pname, price, num, datetime 1, 2011, 12, 1, kaneko, orange A, 1.2, 10, 2011-12-01 10:42:48 2, 2011, 12, 1, miyamoto, Apple M, 2.5, 2, 2011-12-01 10:42:59 3, 2011, 12, 3, kaneko, orange B, 1.2, 8, 2011-12-03 11:08:56 4, 2011, 12, 4, miyamoto, Apple L, 3, 1, 2011-12-04 15:35:12
CVS ファイルの1行単位での読み込みでは、 CSV ファイルの各行が,文字列の配列になる (The unit of read is a 'line'. A line become an array).
require "csv" CSV.open("hoge.csv", "r") do |row| p row end
◆ 実行結果の例 (execution result example)
1行目がヘッダー.2行目以降が本体
require "csv" reader = CSV.open("hoge3.csv", "r") header = reader.take(1)[0] p header p "=================================" reader.each do |row| p row end
◆ 実行結果の例 (execution result example)
1行目がヘッダー.2行目以降が本体
require "csv" reader = CSV.open("hoge3.csv", "r") header = reader.take(1)[0] T = Hash::new header.each do |attr| T[attr.strip] = [] end reader.each do |row| i = 0 row.each do |item| T[header[i].strip].push(item.strip) i = i + 1 end end
◆ 実行結果の例 (execution result example)
#! ruby -Ks # coding: windows-31j require "csv" def string_type(s) # + は一回以上、*は0回以上 ^ 行頭 $ 行末 # 浮動小数点数 123.45, -123.45, -123.45 など if( ( s =~ /[-+]?([0-9]*\.[0-9]+$)/ ) == 0 ) return "real" # 浮動小数点数 123.45e-06 など elsif( ( s =~ /[-+]?([0-9]*\.[0-9]+)e[-+][0-9]*$/ ) == 0 ) return "real" # 浮動小数点数 123e-06 など elsif( ( s =~ /[-+]?([0-9]+)e[-+][0-9]*$/ ) == 0 ) return "real" # 整数 elsif( ( s =~ /[-+]?([0-9]+)$/ ) == 0 ) return "integer" end end if __FILE__ == $0 CSV.open("hoge2.csv", "r") do |row| s = "" row.each do |field| s << field.strip type = string_type(field.strip) if ( type != nil ) s << ":" s << type end s << "," end puts s end end
◆ 実行結果の例 (execution result example)
カンマ区切りなのだけど CSV の流儀に従っていないという場合です. 例えば,「101, He said "Hello"」はカンマ区切りですが,CSV の流儀に合致しません. これは,「101, "He said ""Hello"""」のように変換する必要がある. ここでは「""」で1つの半角のダブルクオートを表すことを「エスケープ」と呼んでいます.
#! ruby -Ks # coding: windows-31j require 'pp' def escape_double_quote(s) # 文字列が 「"」 (半角のダブルクオート)を含むとき # 「"」 を 「""」 に置換するとともに, # 文字列全体を「"」で囲む.これは CSV ファイルの流儀 if ( /"/ =~ s ) # 置換し,文字列全体を「"」で囲む return '"' + s.gsub('"','""') + '"' else # そのまま返す return s end end if __FILE__ == $0 print escape_double_quote('hoge hoge hoge') print "\n" print escape_double_quote('hoge "hoge" hoge') print "\n" end
◆ 実行結果の例 (execution result example)
require "csv" # open for write f = open("hoge2.csv", "w") writer = CSV::Writer.generate(f) # write for i in 1..200 writer << [i, " File" + sprintf("%06d", i) + ".png"] end f.close()
CSV ファイルの 4, 5 列目を .gsub(/a/, "A") で置き換える。
require "csv" # open for write f = open("hoge2.csv", "w") writer = CSV::Writer.generate(f) # read and write CSV.open("hoge.csv", "r") do |row| # replace "a" to A inte column 4 and 5 f0 = row[0] f1 = row[1] f2 = row[2] f3 = row[3] f4 = row[4].gsub(/a/, "A") f5 = row[5].gsub(/a/, "A") f6 = row[6] f7 = row[7] f8 = row[8] writer << [f0, f1, f2, f3, f4, f5, f6, f7, f8] end f.close()
◆ 実行結果の例 (execution result example)