Sunday, January 3, 2016

Basic File I/O in Ruby

Need a reference text for the Ruby programming language? Get the Well-Grounded Rubyist.

Reading data from a file as well as writing data to a file has been made easy with Ruby. This article will cover how to read from a file and how to write to a file using Ruby's File class.

Let us jump right into it: to read each line from a file, use a block for the foreach() method of the File class.

File.foreach('somefile.txt') do |line|
  puts line
end

Each line will contain a \n newline character, so if you would like to chop it off, use

line.chomp

Assuming somefile.txt contains the following contents:

This is a sample file
With some contents within
This is the last line :)

The output of the Ruby script would be:

$ ruby basic_file_io.rb
This is a sample file
With some contents within
This is the last line :)

So you iterate through each line of the file and do something with that line. Specify the filename as the method parameter and then do a block with a parameter that will be used to hold each line, |line|.

There is one problem with the above construct: what if the file did not exist? Then surely you will get a problem:

basic_file_io.rb:1:in `foreach': No such file or directory - doesnt_exist.txt (Errno::ENOENT)

I tried to open a file called "doest_exist.txt" to read, but it did not exist, so I got an error.

To get around that error, you can either: handle the exception, or first check if the file exists before trying to do anything with it.

The following code illustrates how to handle exceptions:

begin
  File.foreach('doesnt_exist.txt') do |line|
    puts line
  end

rescue Exception => e
  puts "Oh no, something went terribly wrong!"
  puts e.message
  puts "Maybe we can do something about that problem here . . ."
end

Output:

$ ruby basic_file_io.rb
Oh no, something went terribly wrong!
No such file or directory - doesnt_exist.txt
Maybe we can do something about that problem here . . .

As you can see, you could have done something about the problem using the exception construct. You start off by saying "begin" then put everything you are attempting to do right afterward. Then, you make a "rescue" section with an object to hold the data for the exception; I used the name "e" above. Within the rescue section, you can determine how the program should behave in case some problem happens. Using e.message, you can also see the description of the problem. Finally, don't forget to finish everything with an "end."

Another way to handle problems when trying to read a file is using the "exist?" method. If you don't want to use exceptions, then you can try this out:

if File.exist? 'sample.txt'
  File.foreach('sample.txt') do |line|
    puts line.chomp
  end
else
  puts "I am sorry, but the file does not exist."
end

Assuming sample.txt does not exist, the output is:

I am sorry, but the file does not exist.

Now, let us see how to write to a file. In a similar fashion, we use the File class and call the open() method with a block that will do something to the file:

File.open('newfile.txt', 'w') do |file|
  file.puts "Hello everyone!"
  file.puts "This will be a brand new file!"
  file.puts "Just one more last line"
end

The above will open the file "newfile.txt" for "write." That is, a new file will be created and IF there is already a file named "newfile.txt," it will be completely wiped out and OVERWRITTEN. So be careful with the "w" mode. :) Moving on, you just use the |file| parameter to add things to the file. Just call file.puts with whatever string you want to add to the file contents. Because "puts" adds a newline character, each of those sentences written in the code above will be in their own line. When you take a look at the file, you get this:

$ cat newfile.txt
Hello everyone!
This will be a brand new file!
Just one more last line

Pretty cool, isn't it? Now, there are other modes that let you append to files, etc. I will leave it to you to Google it and find out about them if you don't already know. Here is a big hint: http://stackoverflow.com/questions/3682359/what-are-the-ruby-file-open-modes-and-options

And to conclude everything, just an important note: files are automatically *closed* at the end of each block, so there is no need to call a method to close the file, like in other programming languages such as C++ and PHP.

In summary, Ruby lets you handle file I/O with the File class. You can iterate over a file to read each line using the File.foreach() method. There might be cases in which the file will not exist, so you can handle issues with an exception (begin-rescue-end construct). There is also the option to use the File.exist? method to check whether a file exists. Writing to files can be done using the File.open() method in combination with a block with instructions to add something to the file. You can use the puts method on the block parameter to add some content to the file.

Looking for a reference text for Ruby? Get the Well-Grounded Rubyist.

No comments:

Post a Comment