Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stream Closed IO Error when using CSV Library

I am trying to get an array of hashes from parsing a CSV file using CSV library.

I currently have this method which works:

def rows
  rows = []

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

  rows
end

but when I change it to this I get the stream closed error.

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

thanks

like image 413
Ollie2619 Avatar asked Sep 12 '25 11:09

Ollie2619


1 Answers

If you look at the source code of ::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

It internally, opening the file using CSV::open, with a block. So, once the block is closed, the IO object got closed, internally. Now as you are trying to access the closed IO object, you are getting the error.

From the doc of CSV::open

This method works like Ruby’s open() call, in that it will pass a CSV object to a provided block and close it when the block terminates,...

The IO object returned by ::foreach is actually returned by the CSV::open, within the method def self.foreach ....

Example :

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
like image 97
Arup Rakshit Avatar answered Sep 15 '25 00:09

Arup Rakshit