1

I'm trying to open a simple CSV file in Ruby, find a particular key, increment its value by one, then re-save it.

Example CSV file:

store1,0
store2,0
store3,0
...etc.

Ruby code:

require 'csv'

currentStore = store  # store is passed as a parameter
if currentStore.nil? && currentStore.empty?
    currentStore = "nil"

store_data = {}

File.open('store_count.csv').each_line {|line|
    line_data = line.split(",")
    if !line_data[1].nil? && !line_data[1].empty?
        store[line_data[0]] = line_data[1].strip.to_i
    else
        next
    end
}

if store_data.key?(currentStore)
    store_data[currentStore] += 1

    CSV.open("store_count.csv", "wb") {
        |csv| store_data.to_a.each {
            |elem| csv << elem
        }
    }
end

So for example, if I increment 'store3', I need my file to look like:

store1,0
store2,0
store3,1
etc...

After I increment the value, I need to re-save to CSV.

  • 1
    Your best option is to read the CSV and write it to new CSV, and during the process update the values that matches your conditions – Wand Maker Jun 20 '16 at 16:45
  • 1
    It's a bad idea to load the file into memory, modify it then rewrite it to the original file. If the job fails the original file can be corrupted if it's partially overwritten. As @WandMaker said, write to a new CSV file. Then, when you're finished processing rename the original file, rename the new file to the old original name, then do whatever you want with the old one. Also, use line-by-line I/O. It's as fast as [slurping a file](http://stackoverflow.com/q/25189262/128421) without scalability problems. – the Tin Man Jun 20 '16 at 17:13
  • 1
    We'd like a more complete example of your attempt to solve the problem. As is, you've only demonstrated the bare start of it, so it looks like you want us to write a tutorial, or write the code for you, neither of which are on-topic. Please read "[mcve]" and "[ask]" including the linked pages. – the Tin Man Jun 20 '16 at 17:16
  • I apologize for the lack of code, however as mentioned I'm a beginner with Ruby, and having trouble with the syntax. I don't have more complete code, as I've made several attempts to solve this, and revised my code repeatedly. Unfortunately it's not working, and so I didn't see the point of posting bad code that I had already deleted. I'll try to do my best to recreate the bad code that I had. – forever_baffled Jun 20 '16 at 17:37
  • I have modified my original query as outlined above. Hopefully this meets the required criteria. – forever_baffled Jun 20 '16 at 17:55

1 Answers1

0

You cannot read and write at the same time.

What are the Ruby File.open modes and options?

If you are dealing with a small file, where you can fit everything into the memory, this should be enough.

temp_file = File.open('temp.csv', 'w')
CSV.readlines('temp.csv').each do |line|
  temp_file << "#{line[0]},#{line[1].to_i + 1}\n"
end

temp_file.flush
temp_file.close

If you want to rename the file, you can do this

`rm store.csv`
`mv temp.csv store.csv`
Community
  • 1
  • 1
Edmund Lee
  • 2,514
  • 20
  • 29
  • 3
    It's not good practice to load files into memory unless it's guaranteed that they'll never grow in size. It's very common that people develop against a small file, loading it into memory, then in production encounter a file that exceeds the available memory taking the code to its knees. Line-by-line I/O is as fast and sidesteps the problem. Also, rename the original, then rename the new file to the original file's name, *THEN* it's safe to remove the original. http://stackoverflow.com/a/18261457/128421 is a good read. – the Tin Man Jun 20 '16 at 17:17