Ruby — Working with Files

Shalinga Manasinghe
10 min readFeb 5, 2022

INTRODUCTION

I’ll be taking a look at the different functions available to us in the standard Ruby language that will allow us to read from and write to files. We’ll take a look at how files behave as we execute these various functions. In this we are not going to talk about everything we can do with a file using Ruby, We are going to talk about how to write to a file and how to read from a file. And we are going to talk about 3 file types: Text, CSV and JSON.

To get started we are going to need a few tools. The first one we need is a text editor, there are few text editors available so you can use any one of them. I personally use Atom by GitHub or Visual Studio Code by Microsoft. Next thing we need is a terminal. This is where we will be calling our Ruby interpreter to execute our Ruby code. And make sure that you install Ruby on your computer.

GETTING STARTED

Make sure that you have all files (.rb, .txt, .vsc, .json) in the same directory and that the terminal is open within that directory. To keep things standard and simple, all our code will be executed within a single file, which we call main.rb.

READING FROM TEXT FILES

In this section first read the file from its location and then print out its content in the terminal to verify that our program has indeed read the file. First we are going to create a text file with specific content so we can verify file content. I’m going to call my text file “welcome.txt” and I’m going to add “Welcome to Ruby” as its content.

There are several ways to do this part, we are going to try the simplest way.

We are going to create a variable containing file location with file name or its relative path. Since it’s in the same directory as the main.rb file we can simply set our veritable value to file name.

file_location = “welcome.txt”

OR

file_location = “./welcome.txt”

Now as the next step we are going to open the file and set it to another variable called “file”. This will create a file object where we can use any methods available to Ruby file object class.

file = File.open(file_location)

Now we are going to read the file object and assign the content to a variable called “content”. For that we are going to use an instance method called “read” from File class.

content = File.read(file)

Now we have text file content. Only thing left is to verify it by printing it in the terminal so that we can use the code below. Method “PUTS” helps us to print anything with a new line at the end. You can also use the “print” method too, but it does not add a new line at the end. I always use the “puts” method.

puts content

Now main.rb looks like this.

file_location = “./welcome.txt”
file = File.open(file_location)
content = File.read(file)
puts content

We can change it a little bit. Instead of using both “open” and “read” methods, we can simply use the “read” method. Read method will open and read the file at the same time. So we can change our code to look like this.

file_location = “./welcome.txt”
content = File.read(file_location)
puts content

Lets run this command in our terminal and see the output: ruby main.rb

WRITING TO TEXT FILE

Let’s now take a look at the functions that will allow us to write to a file using Ruby. There are two approaches when writing to a file, the first one is to replace a file that completely overwrites its content with something new. The second approach is to append to a file. This means that we simply add more content to the existing content of the file at hand.

First we are going to overwrite the file content. First we are going to clear out our main.rb file or you can create a new .rb file for this one. And we are going to use the same .txt file.

file_location = “./welcome.txt”
file = File.open(file_location)
content = “Overwriting file content.”
File.write(file, content)

Let’s go through the above code section.

We already know what line one and two do. In line three we are assigning a text to a variable, this text will be the one that is going to be new content in the “welcome.txt” file. And from the last line we overwrite the file’s content. Here we only pass two variables to the “write” method, one is file location and other one is text we want to write. This will replace whatever text already in the text file. For testing, you can run this command once and change the content variable value and run it again. And you will see that text file content changes to the second variable value and the first one disappears. That is a problem when you want to work on a text file and every-time you add a text previous, the content gets erased. We can avoid that by appending our text to the text file content.

First we are going to add some text to our text file content. Then we are going to modify our program. We are going to use the same code we used to write to file and pass one more variable to the File.write() method called “mode”. This will add new content at the end of the file instead of overwriting it.

file_location = “./welcome.txt”
file = File.open(file_location)
content = “Overwriting file content.”
File.write(file, content, mode: “a”)

That is how you read and write from text files in Ruby.

FILE FORMAT CSV

So what is a CSV file? CSV stands for a comma-separated value. This means that the individual pieces of data found within a CSV file are separated with the comma, at least by default. CSV files are just normal text files with a particular format and nothing special about it. Since it’s a normal text file you can open them in any text editor. CSV files represent data in a tabular fashion. This means that data is structured in a set of rows and columns with a given dimensionality. Now let’s see how we can read from a CSV file.

READING FROM CSV FILE

As we did for a text file application we are going to create a main.rb file and sample CSV file in the same directory. We’ll name our CSV file as books.csv.

To read csv files we are going to use Ruby’s builtin library called “csv”.

This is my sample csv file content

title, author
Alice in Wonderland, Mark Twain
Harry Potter, J. K. Rowling
Naruto, Masashi Kishimoto
require ‘csv’file_location = “books.csv”
content = File.read(file_location)
data = CSV.parse(content, headers: true)
data.each do |d|
puts “TITLE: #{d[0]} AUTHOR: #{d[1]}”
end

If you see the output you notice that it prints the header section (title, author) of the csv file. To prevent that you need to pass headers true in the “parse” section. Once I pass headers true, it will assume that the first row actually pertained to the headers of the CSV file, and I can use that information, that is the header names as the indicator for the actual value spur line in the CSV file.

require ‘csv’file_location = “books.csv”
content = File.read(file_location)
data = CSV.parse(content, headers: true)
data.each do |d|
puts “TITLE: #{d[‘title’]} AUTHOR: #{d[‘author’]}”
end

WRITING TO CSV FILE

Let’s now use what we learned to generate a CSV file. Let’s imagine we have a bunch of book titles and authors that we received from somewhere and we need to write them to a CSV file for future usage. I’ll start off by creating a main.rb file. First I’m going to require a CSV library. Then I’m going to create a variable called file_location with a value for the file name. Let’s call that file ‘books.csv’. Let’s say we have a two-dimensional array with all the books data.

books = [
[“book”, “author”],
[“Alice in Wonderland”, “Mark Twain”],
[“Harry Potter”, “J. K. Rowling”],
[“Naruto”, “Masashi Kishimoto”],
]

First element of the outer array would pertain to the headers of my CSV file, so that would be the book and author. From the second element onwards we get the book name and author.

Now we are going to create a variable call content so we can write that to our csv file. This content variable contains all the data we need to write to our csv file.

content = data.map{|d| d.join(“,”)}.join(“\n”)

Here we are going to join all the arrays and their elements using commas and new line characters. Now we can write this to our file using:

File.write(file_location, content)

Now we can run our ruby script and see that it writes to our file. If you are going to create a new file every time you receive data, we can use this script, but if you want to append data to an already existing file we can modify this script like below.

require ‘csv’file_location = “books.csv”
CSV.Open(file_location, “a”) do |f|
f << [“Naruto”, “Masashi Kishimoto”]
end

This way you can append data to your existing csv file.

WORKING WITH JSON

JSON standard for JavaScript Object Notation. We use JSON to pass data around web applications. These days, JSON can be used for a wide variety of data‑driven applications, such as configuration files for various software, messaging formats for web services, and applications talking to one another internally. JSON file is a large text that is formatted and saved to file with “.json” extension. JSON can have within it scalar values, arrays, objects, or even objects within arrays, which, in turn, also contain complex structures of more objects, all of this with a simple key value pair syntax.

READING FROM JSON FILE

Now let’s take a look at how we can process JSON data from within our Ruby code. Earlier, we mentioned that JSON data can be stored as a simple text file. Therefore, a file with JSON in it can be represented as a string in Ruby similar to what we’ve seen in the CSV module. Unlike CSV, JSON can tend to be more complex with nested attributes and no definite pattern. Parsing it manually will serve to be more challenging and more error prone at the same time. The preferred way to properly handle JSON data from Ruby is to programmatically represent and parse JSON strings as Ruby objects using Ruby’s native JSON library.

Like always we are going to start with a local file called “books.json”.

{
“books”: [
{
“title”: “Alice in Wonderland”,
“author”: “Mark Twain”
},
{
“title”: “Harry Potter”,
“author”: “J. K. Rowling”
},
{
“title”: “Naruto”,
“author”: “Masashi Kishimoto”
}
]
}

Let’s create our ruby file and start coding. First line we are going to require our json library, then we are going to create a veriablecall “file_location” and assign file path to its value. Then we arte going to read that file and pass it to a variable call content. Now we have a string version of json data found in that file. Next we are going to parse that value and convert it to a ruby object. And assign it to a new variable called “data”. We can get an array of book json objects by accessing the “books” key in “data” object.

We can loop through the “books” key and get the individual book json object. From that json object we can access “title” and “author” keys.

require ‘json’file_location = “books.json”
content = File.read(file_location)
data = JSON.parse(content)
data[“books”].each do |d|
puts “TITLE: #{d[“title”]} AUTHOR: #{d[“author”]}”
end

Now you can assign those values to variables and use them in your application.

When you get data from an API most of the time that data is received in json format. So you can use some part of this programme to access those data for your application.

WRITING TO A JSON FILE

Let’s talk about how to write data to a json file. As usual we are going to require the ruby json library at the beginning. Then we are going to create a hash containing our json data. Or you can get json data from any API. Then we can convert that to a json object using the “to_json” method and assign it to a variable call data and finally we can write it using the “File.write” method.

require ‘json’data = {
“books”: [
{
“title”: “Alice in Wonderland”,
“author”: “Mark Twain”
},{
“title”: “Harry Potter”,
“author”: “J. K. Rowling”
},{
“title”: “Naruto”,
“author”: “Masashi Kishimoto”
}
]
}
content = data.to_json
File.write(“new_books.json”, content)

Let’s run the application. Now if you open the “new_books.json” file you can see all our content in a single line. It’s hard to read when it has thousands of data and also it takes much longer to read or open in a text editor when all the data is in a single line. So we are going to change our programme to make our json content pretty.

Now our programme looks like this:

require ‘json’data = {
“books”: [
{
“title”: “Alice in Wonderland”,
“author”: “Mark Twain”
},{
“title”: “Harry Potter”,
“author”: “J. K. Rowling”
},{
“title”: “Naruto”,
“author”: “Masashi Kishimoto”
}
]
}
content = JSON.pretty_generate(data)
File.write(“new_books_1.json”, content)

JSON.pretty_generate” converts your single line json object into a multi line json object.

This is how you write json data into a file.

Now you know how to read from text, csv and json files and write to all those file formats. Finally I want you to know none of these codes are optimized to use in a large scale application. So if you are going to use any of these methods, remember to optimize, break into multiple methods and use best practices. This article touches on the surface of these file types and how to work with them and it’ll help you to get started working with files. Read more about files and continue to learn.

--

--