Writing to Files

Compared to writing to other processes, writing to files is a relative breeze—there’s only a limited number of ways to do it. This isn’t really surprising, I suppose, but what’s interesting is typically the content—what’s actually being written—rather than the mechanism of writing.

In Chapter 1, Reading from Files, we looked at how we could use open to obtain a File object that enabled us to read from a file. It looked like this:

 
File.open(​"file.txt"​) ​do​ |file|
 
contents = file.read
 
end

What if, rather than using read to read from the file, we tried to use write or puts to write to it—something like this?

 
File.open(​"file.txt"​) ​do​ |file|
 
file.puts ​"Hello, world"
 
end

If we ran this code, we’d get the following exception:

 
IOError: not opened for writing

That’s because the default behavior of File.open is to open the file in read-only mode. Attempts to write the file, as we’ve just seen, are met with resistance.

We can control this behavior through the second argument to File.open or open. It tells Ruby the mode to use when opening our file. Its possible values are:

r

Read-only mode. We can read from the file freely, but we can’t write to it. This is the default mode, which is why we saw our error when trying to use the File object to write to the file.

If the file doesn’t exist, we’ll quite reasonably get an error telling us so, since it doesn’t make sense to read from a file that doesn’t exist.

r+

Read-write mode. This allows us to both read from and write to the file. If the file doesn’t exist, we’ll get an error just like we would when opening the file in read-only mode.

This mode is useful when you care about the current contents of the file but will be overwriting them. You can read the file and then when you’re done, use puts or write to write the new content—allowing you, for example, to do some sort of substitution of the contents or to insert new content into the start or middle of the file.

w

Write-only mode. If the file doesn’t exist, it will be created. If it does exist, opening it in this mode will cause it to be truncated (that is, it will cause all of its content to be deleted).

This mode is useful when you’re writing the entire content of the file, and you don’t care if the file exists or has any current contents. This is perhaps the most common mode to use when writing files.

w+

Read-write mode. This allows us the same flexibility as opening the file in r+ mode but will create the file for us if it doesn’t exist (and if it does, it will truncate the file). Rarely seen in the wild, it’s occasionally useful.

a

Append mode. Like w mode, the file will be created if it doesn’t exist. If the file does exist, though, content will be written to the end of the file, hence the name.

Perhaps the most common use of append mode is to write to a log file. In such a file, we want the content to be ordered chronologically, so that the oldest lines are first and the newest lines are last. Using append mode will do this for us.

For example, if our log file currently contains:

 
21:00 Did a thing

then the following code:

 
File.open(​"log.txt"​, ​"a"​) ​do​ |log|
 
log.puts ​"21:01 Did another thing"
 
end

will result in log.txt having the following content:

 
21:00 Did a thing
 
21:01 Did another thing

No other mode will preserve the contents of the file when writing to it in this way. It’s not possible, then, to prepend a line to a file. If you want to keep the existing contents and merely add to them, you’re limited to append mode.

a+

Read-write append mode. If the file exists, it will open it for both reading and writing, and content will be written to the end of the file. If the file doesn’t exist, it will be created.

In our previous example, this would enable us to both read the current contents of the log and write new log entries with the same File object.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.142.69.168