Writing to a File

Problem

You want to write some text or Ruby data structures to a file. The file might or might not exist. If it does exist, you might want to overwrite the old contents, or just append new data to the end of the file.

Solution

Open the file in write mode ('w'). The file will be created if it doesn't exist, and truncated to zero bytes if it does exist. You can then use IO#write or the << operator to write strings to the file, as though the file itself were a string and you were appending to it.

You can also use IO#puts or IO#p to write lines to the file, the same way you can use Kernel#puts or Kernel#p to write lines to standard output.

Both of the following chunks of code destroy the previous contents of the file output, then write a new string to the file:

	open('output', 'w') { |f| f << "This file contains great truths.
" }
	open('output', 'w') do |f|
	 f.puts 'The great truths have been overwritten with an advertisement.'
	end
	
	open('output') { |f| f.read }
	# => "The great truths have been overwritten with an advertisement.
"

To append to a file without overwriting its old contents, open the file in append mode ('a') instead of write mode:

	open('output', "a") { |f| f.puts 'Buy Ruby(TM) brand soy sauce!' }
	
	open('output') { |f| puts f.read }
	# The great truths have been overwritten with an advertisement.
	# Buy Ruby(TM) brand soy sauce!

 

Discussion

Sometimes you'll only need to write a single (possibly very large) string to a file. Usually, though, you'll be getting your strings one at a time from a data structure or some other source, and you'll call puts or the append operator within some kind of loop:

	open('output', 'w') do |f|
	 [1,2,3].each { |i| f << i << ' and a ' }
	end
	open('output') { |f| f.read } # => "1 and a 2 and a 3 and a "

Since the << operator returns the filehandle it wrote to, you can chain calls to it. As seen above, this feature lets you write multiple strings to a file in a single line of Ruby code.

Because opening a file in write mode destroys the file's existing contents, you should only use it when you don't care about the old contents, or after you've read them into memory for later use. Append mode is nondestructive, making it useful for files like log iles, which need to be updated periodically without destroying their old contents.

Buffered I/O

There's no guarantee that data will be written to your file as soon as you call << or puts. Since disk writes are expensive, Ruby lets changes to a file pile up in a buffer. It occasionally flushes the buffer, sending the data to the operating system so it can be ritten to disk.

You can manually flush Ruby's buffer for a particular file by calling its IO#flush method. You can turn off Ruby's buffering altogether by setting IO.sync to false. However, your operating system probably does some disk buffering of its own, so doing these things won't neccessarily write your changes directly to disk.

	open('output', 'w') do |f|
	 f << 'This is going into the Ruby buffer.'
	 f.flush # Now it's going into the OS buffer.
	end
	
	IO.sync = false
	open('output', 'w') { |f| f << 'This is going straight into the OS buffer.' }

 

See Also

  • Recipe 1.1, "Building a String from Parts"
  • Recipe 6.6, "Reading the Contents of a File"
  • Recipe 6.19, "Truncating a File"


Strings

Numbers

Date and Time

Arrays

Hashes

Files and Directories

Code Blocks and Iteration

Objects and Classes8

Modules and Namespaces

Reflection and Metaprogramming

XML and HTML

Graphics and Other File Formats

Databases and Persistence

Internet Services

Web Development Ruby on Rails

Web Services and Distributed Programming

Testing, Debugging, Optimizing, and Documenting

Packaging and Distributing Software

Automating Tasks with Rake

Multitasking and Multithreading

User Interface

Extending Ruby with Other Languages

System Administration



Ruby Cookbook
Ruby Cookbook (Cookbooks (OReilly))
ISBN: 0596523696
EAN: 2147483647
Year: N/A
Pages: 399

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net