![]() |
Altering 1 line in an existing file
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/. |
Re: Altering 1 line in an existing file
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 : john.carter@tait.co.nz New Zealand |
Re: Altering 1 line in an existing file
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/. |
Re: Altering 1 line in an existing file
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 |
| All times are GMT. The time now is 07:05 AM. |
Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.