How can I update one line of correspondence in a text file?

I am trying to write a script that stores some pieces of data inside flat .txt files (these are small files, less than 100 lines).

In any case, I try, in fact, to update one suitable line with a new value for this line, leaving everything else in the file, but I can’t figure out how to change only one line, and not replace the complete file.

Here is my code:

# get file contents as array. array_of_lines = File.open( "textfile.txt", "r" ).readlines.map( &:chomp ) line_start = "123456:" # unique identifier new_string = "somestring" # a new string to be put after the line_start indentifier. # cycle through array finding the one to be updated/replaced with a new line. # the line we're looking for is in format 123456:some old value # delete the line matching the line_start key array_of_lines.delete_if( |line| line_start =~ line ) # write new string into the array. array_of_lines.push( "#{line_start}:#{new_string}" ) # write array contents back to file, replacing all previous content in the process File.open( "textfile.txt", "w" ) do |f| array_of_lines.each do |line| f.puts line end end 

The contents of textfile.txt will always consist of the format:

unique_id: string_of_text

where I can match unique_id with the application data generated by the script to find out which line of text will be updated.

Is there a better way to do what I'm trying to do?

It seems a little inefficient to read the entire file in memory, iterate over everything, only to update one line in that file.

+4
source share
1 answer

You cannot do what you want if the new data that you write does not have the same length as the old data.

If the length is different, then all bytes in the file must be transferred after the change. Moving data files always involves rewriting everything (starting from the moment of modification). In this case, you can also rewrite the entire file, since your files are so small.

If the replacement data is the same length, you can use IO.seek to put the file pointer in the appropriate place, and then just use write to enter the replacement data.

If you still do not want to overwrite the entire file, but instead just move the data (if the replacement length is different), then you need to seek to the right place, and then write everything to end the file from this point forward. If the replacement is shorter, you will also need to call File.truncate to resize the file.

+4
source

All Articles