Ruby File Handling

A file is a named location used for storing data. For example, main.rb is a file that is always used to store Ruby code.

In Ruby, you can read from, write to, and manipulate files using the built-in File class. This process is known as File Handling.


Opening a File in Ruby

We need to open a file first to perform any operations on it. For this, we use the File.open method. Let's look at an example:

Suppose we have a file named file1.txt.

Contents of Our File
Contents of Our File

We can open this file using the File.open method:

my_file = File.open("file1.txt", "r")

Here,

  • file1.txt - The name of the file we want to open.
  • r - Open the file for reading.

This code creates a File object named my_file. Now, we can use this object to work with files.


More on File Opening

Different File Opening Modes

Ruby allows us to open files in different modes (read, write, append, etc.), based on which we can perform different file operations. For example,

my_file = File.open("file1.txt")

Here, we are opening the file in the read mode (we can only read the content, not modify it).

Note: By default, Ruby files are open in read mode. Hence, the code File.open("file1.txt") is equivalent to File.open("file1.txt", "r").

Different Modes to Open a File in Ruby

Mode Description
r Open a file in reading mode (default).
w Open a file in writing mode (creates a new file or overwrites an existing one).
a Open a file in appending mode (adds content at the end of the file).
r+ Open a file for reading and writing.
w+ Open a file for reading and writing, but it truncates (clears) the file.
a+ Open a file for reading and appending.

Here are a few examples of opening a file in different modes,

# Open a file in default mode (read)
# Equivalent to open("test.txt", "r")
my_file = File.open("test.txt")

# Open a file in write mode 
my_file = File.open("test.txt", "w")  

# Open a file in read and write mode
my_file = File.open("test.txt", "r+")
Opening a File Using its Full Path

We can also open a file using its full path.

file_path = "/home/user/documents/file1.txt"
my_file = File.open(file_path)

In this example, /home/user/documents/file1.txt is a full path to a file named file1.txt located in the /home/user/documents/ directory.


Reading Files in Ruby

Ruby offers several ways to read files. Let's look at two common methods to read it:

1. Using File objects.

Here, we first create a File object like we previously learned. Then, we use the each_line method with a do...end block to print the file contents line by line. For example,

# Create a File object to open a file
my_file = File.open("file1.txt")

# Read the file line by line
my_file.each_line do |line|
  puts line
end

# Close the file
my_file.close

Here, line is a placeholder variable in the loop. In each iteration, the line variable takes a single line from the file and moves to the next line in the following iteration.

Important! Once you create a File object such as my_file, you must close it after you've completed all file operations. This frees your system resources and also ensures data is safely written to the disk.


2. Using a block (auto-closes the file).

You can also use a block where you open the file when defining the loop itself. For example,

File.open("file1.txt", "r") { |file| puts file.read }

Here, file is a placeholder variable that represents the File object we just opened. We then use the read method with the placeholder to read the file.

Important! This code loads the entire contents of the file into memory as a single string. Thus, while this code is easy to read, it's not ideal for large files.

Instead, you can read the file line by line using each_line:

File.open("file1.txt", "r") do |file|
  file.each_line { |line| puts line }
end

In each iteration of this code, the line placeholder stores a single line of the file and moves to the next line in the following iteration.

Note: Using a block is safer and more idiomatic in Ruby, as the file is closed automatically when the block finishes.


Other File Reading Methods

Apart from the read method (which reads the whole file), you can also use the following methods as per your needs:

  • readline - Reads one line of the file.
  • readlines - Reads all lines into an array, where each line is an element in the array.

Let's use these methods to read the following file:

Contents of Our File
Contents of Our File

1. Using the readline method.

my_file = File.open("file1.txt", "r")

puts my_file.readline    # Output: This is a test file.
puts my_file.readline    # Output: Hello from test file.

Here, readline reads a single line of the file and moves the file pointer to the next line. So, when you use readline again, it prints the next line.

2. Using the readlines method.

my_file = File.open("file1.txt", "r")

puts my_file.readlines

# Output:
# This is a test file.
# Hello from test file.

As you can see, readlines reads the entire file.

Difference between read and readlines.

The read method returns the file contents as a single string. For example, read returns the contents of file1.txt as:

# String returned after using 'read' for file1.txt
"This is a test file.\nHello from test file."

On the other hand, the readlines method returns an array, where each line is an element of the array. For example, readlines returns the contents of file1.txt as:

# Array returned after using 'readlines' for file1.txt
["This is a test file.", "Hello from test file."]

Writing to a File

To write to a file, we open the file in "w" (writing) mode and use the write method inside a do loop. Let's try this with our file1.txt file:

File.open("file1.txt", "w") do |file|
  file.write("My text file!")
end

This code creates (or overwrites) file1.txt and writes the string "My text file!" to the file.

Important! "w" will overwrite the file if it already exists.

Since file1.txt already exists, all previous content will be replaced with the new text content inside the write method. So, our file now looks like this:

"w" Overwrites Existing Files

Appending to a File

We open a file in "a" (append) mode to add text to the end of an existing file. Let's see how we can do this using our original file1.txt file:

Original Contents of the File
Original Contents of the File

Then, we can add the sentence "My text file!" using append mode like this:

File.open("file1.txt", "a") do |file|
  file.puts("My text file!")
end

Here, file.puts adds new content to the file (along with a new line at the end) without erasing the original content. So, our file now looks like this:

Appended File Contents
Appended File Contents

You can see that it attached the new text right at the end of the original file content.

To fix this, add a newline character "\n" at the beginning of the appended text:

File.open("file1.txt", "a") do |file|
  file.puts("\nMy text file!")
end

As you can see, writing "\nMy text file!" shifted our appended text to the next line:

Appended File Contents with Newline
Appended File Contents with Newline

Checking if a File Exists

We can use the exist? method to check if a file is present:

if File.exist?("file1.txt")
  puts "File found!"
else
  puts "File not found."
end
Use exception handling to deal with possible problems in file operations.

Instead of a simple if...else statement like the one above, you can use exception handling to make your code more robust and error-proof. For example,

# Try to open the file inside the begin statement
begin
  File.open("file1.txt") do |file|
    puts "File found!"
  end

# If file doesn't exist, print a message
rescue Errno::ENOENT
  puts "File not found."

# Code to execute if there are any other errors
rescue StandardError => e
  puts "An error occurred: #{e.message}"
end

Here,

  • File.open("file1.txt") tries to open the file for reading.
  • If the file doesn't exist, Ruby raises Errno::ENOENT, which we catch and respond with the message "File not found.".
  • The second rescue block catches any other unexpected errors.

Notice that the begin...rescue statement eliminates the need to use the exists? method. The code will simply throw an error if it can't open the file (which is handled by the rescue statements).

To learn more, visit Ruby Exception Handling.


Renaming and Deleting a File

Rename a File

We can rename a file using the rename method:

File.rename("file1.txt", "renamed_file.txt")

Here, we renamed file1.txt to renamed_file.txt.

Delete a File

We can delete a file using the delete method:

File.delete("file1.txt")

Here, we used the delete method to remove file1.txt.


Things to Remember in Ruby File Handling

  • Always close the File object using the close method (unless you're using blocks, which closes the file automatically after the operation).
  • Use blocks with File.open for safer, cleaner code.
  • Handle exceptions (e.g., file not found) using begin...rescue for robust applications.
  • Choose the right mode to avoid accidentally deleting or overwriting data (e.g., use append mode "a" instead of write mode "w" to add new content to an existing file).
Did you find this article helpful?

Our premium learning platform, created with over a decade of experience and thousands of feedbacks.

Learn and improve your coding skills like never before.

Try Programiz PRO
  • Interactive Courses
  • Certificates
  • AI Help
  • 2000+ Challenges