Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > Altering 1 line in an existing file

Reply
Thread Tools

Altering 1 line in an existing file

 
 
Jason
Guest
Posts: n/a
 
      03-05-2007
I'm in the process of creating an application launcher in ruby. I've hit
one little hang up though. I want to have the launcher access a file
containing a log of how many times each application has been run, for
ranking purposes.

So far I have the launcher creating the file if it doesn't exist, but
I'm not clear on how to write to that file or update existing lines in
it.

Example of file:

Firefox Web Browser=7
Archive Manager=3

If I create this file manually I'm able to pull the values out and
manipulate them using the following code:

#Open "rankings" file
rankingsFile = File.new("/home/jasbur/.duckduck/rankings")

#Check each line of "rankings" for existing record, if not assign 1 to
@rankingToWrite
rankingsFile.each_line {|line|
lineMatch = line.match("#{appName.chomp}=")
if lineMatch
existingRanking = lineMatch.post_match.to_i
newRanking = existingRanking + 1
puts "New Ranking for #{appName.chomp} is
#{newRanking}"
else
@rankingToWrite = 1
end
}

What I want to do is take "newRanking" and overwrite the old ranking
(existingRanking) in the file. I've seen some people recommend writing a
whole new file and destroying the old one. It seems like there should be
a more elegant way of doing this though. Any ideas?

--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
 
 
 
John Carter
Guest
Posts: n/a
 
      03-05-2007
On Mon, 5 Mar 2007, Jason wrote:

> I'm in the process of creating an application launcher in ruby. I've hit
> one little hang up though. I want to have the launcher access a file
> containing a log of how many times each application has been run, for
> ranking purposes.


Don't forget the Atomic unit of writing for disk files is a cluster. A
cluster is 4096 bytes on an ext3 fs (I believe)

ie. Even if you just wish to change 1 byte on the disk, the disk is
going to be doing (at least) a 4096 byte write.

> What I want to do is take "newRanking" and overwrite the old ranking
> (existingRanking) in the file. I've seen some people recommend writing a
> whole new file and destroying the old one. It seems like there should be
> a more elegant way of doing this though. Any ideas?


If the file is significantly bigger than 4096 bytes, you can divide it
up into fix length records and to seeks and syswrites.

Although by the time you get into that sort of thing using a standard
ISAM library like libgdbm is often best. Ruby has bindings for it.


John Carter Phone : (64)(3) 358 6639
Tait Electronics Fax : (64)(3) 359 4632
PO Box 1645 Christchurch Email : http://www.velocityreviews.com/forums/(E-Mail Removed)
New Zealand


 
Reply With Quote
 
 
 
 
Jason Burgett
Guest
Posts: n/a
 
      03-05-2007
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?

--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
Gary Wright
Guest
Posts: n/a
 
      03-05-2007

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




 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
One-liners: single quotes; altering first line only; printing thechanges? Adam Funk Perl Misc 9 05-20-2009 07:01 PM
Read a file line by line and write each line to a file based on the5th byte scad C++ 23 05-17-2009 06:11 PM
Existing Dll - using Functions from an existing dll Tristin.Colby@gmail.com Ruby 0 02-05-2008 07:38 PM
Why no existing Java type to existing XML schema binding support? nrm Java 3 04-10-2006 04:52 PM
Altering a Bi-Directional Data Line Daragoth VHDL 4 06-30-2004 09:12 AM



Advertisments