Write CSV to stdout or filename
我想创建一个方法,如果给定一些CSV输出写入文件名,如果没有给出,则写入stdout。
似乎我需要以不同的方式处理对
这可能吗?
以下是我的尝试和错误:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | require 'csv' require 'pathname' require 'csv' require 'pathname' def write_to_csv_or_stdout foo, bar, z=nil z = Pathname.new(z) if z z ||= $stdout res = [[foo, bar,"baz"]] CSV(z) do |csv| res.each do |row| csv << row end end end write_to_csv_or_stdout"foo","bar" # foo # bar #=> foo,bar,baz # write_to_csv_or_stdout"foo","bar","baz" # (NoMethodError) |
这适用于stdout和文件名。
它使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | require 'csv' def write_csv(rows, filename = nil) io = filename ? File.open(filename, 'w+') : $stdout.dup CSV(io) do |csv| rows.each do |row| csv << row end end ensure io.close end rows = [["foo","bar","baz"]] write_csv(rows) #=> foo,bar,baz write_csv(rows, 'test.csv') #=> 'test.csv' written |
我使用辅助方法:
1 2 3 4 5 6 7 | def write_csv(io_or_filename, &block) if io_or_filename.is_a?(IO) CSV.new(io_or_filename, &block) else CSV.open(io_or_filename, 'wb', &block) end end |
这可以代替
1 2 3 4 5 | def some_method(x, y, z = $stdout) write_csv(z) do |csv| csv << # ... end end |
一种解决方案是不使用Pathname对象,因为它不是IO对象。
如果打开文件,则可以像使用stdout对象一样使用它。
1 2 3 4 5 6 7 8 9 10 11 12 13 | def some_method x, y, z=nil puts x puts y z = Pathname.new(z).open if z # <== here you get an IO Object back z ||= $stdout res = [["foo","bar","baz"]] CSV(z) do |csv| res.each do |row| csv << row end end end |