使用CSV库时出现“流关闭IO错误”

4

我正在尝试使用 CSV 库从解析 CSV 文件中获取哈希数组。

目前我有一个可以工作的方法:

def rows
  rows = []

  CSV.foreach(@csv_file.path, headers: true) do |row|
    rows << row.to_hash
  end

  rows
end

但是,当我将它改为这样时,会出现流已关闭的错误。

def rows
  CSV.foreach(@csv_file.path, headers: true).map(&:to_hash)
end

感谢您的提问。
1个回答

6
如果你查看::foreach的源代码:
def self.foreach(path, options = Hash.new, &block)
  encoding =  options.delete(:encoding)
  mode     =  "rb"
  mode     << ":#{encoding}" if encoding
  open(path, mode, options) do |csv|
    csv.each(&block)
  end
end

它在内部使用CSV::open打开文件,使用块。因此,一旦块关闭,IO对象就会在内部关闭。现在,当您尝试访问已关闭的IO对象时,会出现错误。
CSV::open的文档中可以看到:

这种方法类似于Ruby的open()调用,它将向提供的块传递一个CSV对象,并在块终止时关闭它,...

::foreach返回的IO对象实际上是由CSV::opendef self.foreach ...方法中返回的。
例如:
2.1.0 :016 > require 'csv'
 => true 
2.1.0 :017 > CSV.open("Gemfile")
 => <#CSV io_type:File io_path:"Gemfile" encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\""> 
2.1.0 :018 > CSV.open("Gemfile") { |c| c }
 => <#CSV io_type:File io_path:"Gemfile" encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\""> 
2.1.0 :019 > CSV.open("Gemfile") { |c| c }.read
IOError: closed stream

谢谢Arup,那么我有没有更好的方法来完成上述任务,还是就用我已经得到的方法? - Ollie2619
@Ollie2619 你的第一段代码很完美,而且像 Ruby 风格... 我会采用那个。 - Arup Rakshit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接