CSVライブラリの作成
標準ライブラリのCSVクラス見たいなのが作りたかったので練習に作ってみた。
まあ作った理由の半分は必要が有ったからだけど。
標準ライブラリでは自前で以下のような動作ができる。
#csv.rbからコピペ CSV.open("path/to/file.csv", "wb") do |csv| csv << ["row", "of", "CSV", "data"] csv << ["another", "row"] end
単純に考えると自前で作るとこんなのしか思い浮かばない。
これはダサいのでなんとかしたい。
csv = CSV.open("path/to/file.csv", "wb") csv.write(["row", "of", "CSV", "data"]) csv.close
取り合えずcsv.rbをみたりネットで調べて作ってみたので公開。
テストはあまりしていないけど、取り合えず動いたのでまあ気にせずに。
#単純なCSV処理のみ #改行対応はしない class SimpleCSV def SimpleCSV.open(file, mode="r", sep=",", &block) case mode when "r" reader(file, sep, &block) when "w" writer(file, sep, &block) else raise "mode error" end end class <<self private def reader(file, sep, &block) if block begin f = File.open(file, "r") open_reader(f,sep,&block) ensure f.close if f end else File.read(file, mode) end end def writer(file, sep, &block) if block begin open_writer(file,sep,&block) end else CsvFile.open(file, "w", sep) end end def open_reader(f, sep, &block) f.read.split("?n").each do |line| yield(line.split(sep)) end end def open_writer(file, sep, &block) CsvFile.open(file, "w", sep) do |f| yield(f) end end class CsvFile < File def open(path, mode="r", sep=",", perm=0666) @@sep = sep #インスタンス変数だったら<<で使用出来ないのでクラス変数で super(path, mode, perm) end def CsvFile.open(path, mode="r", sep=",", perm=0666) @@sep = sep super(path, mode, perm) end def <<(arg) tmp = [] if arg.kind_of?(Array) tmp = arg.join(@@sep) else tmp << arg end super(tmp) end end end end
#!/usr/bin/env ruby require 'simplecsv' #こんな感じでCSVクラスと同じような感じで使える SimpleCSV.open("a", "w") do |f| f << ["aaa", "bbb", "cc"] end