Gary Wright
3/5/2007 2:49:00 AM
On Mar 4, 2007, at 9:08 PM, Jason Burgett wrote:
> Wow, I appreciate the advice. But, I didn't understand much of that.
> Isn't there any way to just do something similar to a gsub and
> write it
> back?
It isn't all that complicated. Assume you have a file named
'counterfile'
that contains:
counter: 0
The file is a single line of text with the 0 appearing at byte offset 9.
The 'c' in this example is at byte offset 0. Then the following code
will 'update' the counter by overwriting the file starting at byte
offset 9.
File.open('counterfile', 'r+') { |f|
f.seek(9) # position file at byte offset 9
f.puts(ARGV[0]) # write the first command line argument to the file
}
That is it. Stick that code in a file called 'update' and then run:
ruby update 100
Take a look at 'counterfile' and you'll see:
counter: 100
Your file has been updated.
You have to remember that from the OS perspective, a file is simply a
stream
of bytes. The OS doesn't really perceive the file as a collection of
lines of
text. If you ran that code again and gave '2' as the command line
argument,
you're going to end up with a 0 and a newline left over from the
previous write
because the '2' and the newline will only replace the 1 and the first
zero of
'100'.
Simply discarding and rewriting a file can often be much simpler than
figuring out
how to remember file offsets and arrange for a file to be updated in
place.
It can get even more complicated if you are dealing with multi-byte
text encodings.
In any case, File#seek is the basic way to move to a new position in
a file
is ultimately how random access I/O is implemented.
Gary Wright