Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to parse a CSV file, update a field, then save

Tags:

ruby

csv

I need to read a CSV file, update a field, then save the changes. I have everything working fine except saving my changes to the field I'm updating:

require 'csv'
@parsed_file = CSV::Reader.parse(File.open("#{RAILS_ROOT}/doc/some.csv"))
@parsed_file.each_with_index  do |row, x|
  address = row[5]
  l = Location.address_find(address)
  if l != nil
    puts "#{l.name} at #{l.address}"
    row[14] = l.store_code
    puts row[14]
  else
    puts "No matching address Found!!!"
  end
  #What do I do here? Something like this? CSV::Writer.generate(@parsed_file) 
end

What do I do here? How do I save the changes I made and update the file?

like image 699
thatmiddleway Avatar asked Aug 24 '10 21:08

thatmiddleway


1 Answers

What I would do is write the updated records to a new file and then, if you want, after you have finished your program can delete the old file and rename the new file to have the original file name.

To do this I would open the output file at the top of your code, outside the each_with_index loop. e.g.

csv_out = CSV::Writer.generate(File.open('new.csv', 'wb'))

Then inside your each_with_index loop you can write the current row to the new file like this:

csv_out << row

Then at the end you can close the new file:

csv_out.close

As mentioned in the comments, CSV::Writer is no longer in the standard library. An equivalent version of the code using the newer CSV.foreach (for reading) and CSV.open (for writing) is:

CSV.open("path/to/file.csv", "wb") do |csv_out|
  CSV.foreach("#{RAILS_ROOT}/doc/some.csv") do |row|
    address = row[5]
    l = Location.address_find(address)
    if l != nil
      puts "#{l.name} at #{l.address}"
      row[14] = l.store_code
      puts row[14]
    else
      puts "No matching address Found!!!"
    end
    csv_out << row 
  end
end
like image 126
mikej Avatar answered Nov 10 '22 00:11

mikej