Ruby 将CSV写入标准输出或文件名

Ruby 将CSV写入标准输出或文件名,ruby,csv,oop,Ruby,Csv,Oop,我想制作一个方法,如果给定,则将一些CSV输出写入文件名,如果未给定,则写入标准输出 似乎我需要根据调用的是文件还是标准输出,以不同的方式处理对CSV的调用,但我确实希望将输出流z视为可以写入的内容,而不必考虑它是磁盘上的文件还是标准输出流 这可能吗 以下是我的尝试和错误: require 'csv' require 'pathname' require 'csv' require 'pathname' def write_to_csv_or_stdout foo, bar, z=nil

我想制作一个方法,如果给定,则将一些CSV输出写入文件名,如果未给定,则写入标准输出

似乎我需要根据调用的是文件还是标准输出,以不同的方式处理对
CSV
的调用,但我确实希望将输出流
z
视为可以写入的内容,而不必考虑它是磁盘上的文件还是标准输出流

这可能吗

以下是我的尝试和错误:

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)
需要“csv”
需要“路径名”
需要“csv”
需要“路径名”
def write_to_csv_或stdout foo,bar,z=nil
z=路径名。如果z,则为新(z)
z | |=$stdout
res=[[foo,bar,“baz”]]
CSV(z)do | CSV|
res.每个do |行|
csv foo、bar、baz
#写到csv或“foo”、“bar”、“baz”
#(命名者)

一种解决方案是不要只使用Pathname对象,因为它不是IO对象

如果打开该文件,则可以使用与使用stdout对象相同的方法来使用它

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
def某些方法x,y,z=nil
放x
放在

z=Pathname.new(z)。如果z#则打开此选项适用于标准输出和文件名

它使用
$stdout.dup
能够在不关闭
$stdout
的情况下关闭
io

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
需要“csv”
def write_csv(行,文件名=nil)
io=文件名?打开(文件名为“w+”):$stdout.dup
CSV(io)do | CSV|
行。每行|
csv foo、bar、baz
写入_csv(行“test.csv”)
#=>写入“test.csv”

我会使用助手方法:

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
这可以用来代替CSV(…)

def some_方法(x,y,z=$stdout)
写_csv(z)do | csv|

你的目标是什么?请不要使用像
some_method
x
y
z
这样的通用名称。特别是对于未使用的变量。是否可以告诉
CSV(z)
写入新文件
z
?因为如果
z
不存在,我就不会得到
这样的文件或目录@rb_sysopen
@mbigras,你需要用
w
w+
属性打开
z
。你认为这种方法更好吗,因为
z
的条件赋值是线性读取而不是分支?我在这方面不能客观一个<代码>z=x,如果z;但是z | |=y
看起来不太对劲。这是分支。感谢您的回复!我退房了。您不需要
开始
结束
关键字来确保
正常工作:)@mbigras:谢谢。rubocop同意你的观点。如果打开失败,你可能想在关闭时添加一个零检查:
io.close if io
@KeithBennett:interest。
File.open
真的会返回
nil
?我认为要么引发错误,要么打开文件。你有没有这样一个例子,
io.close
会因为一个命名错误而失败?@EricDuminil这是一个很好的观点。如果代码以以下任何一种方式更改,则nil检查会更安全:1)在文件打开之前添加了可能引发错误的内容,2)出于其他目的将条件文件关闭(并设置为nil)添加到方法体中。也就是说,这段代码很好,谢谢你的更正。
def some_method(x, y, z = $stdout)
  write_csv(z) do |csv|
    csv << # ...
  end
end