Back-end Engineering Articles

I write and talk about backend stuff like Ruby, Ruby On Rails, Databases, Testing, Architecture / Infrastructure / System Design, Cloud, DevOps, Backgroud Jobs, some JS stuff and more...

Github:
/danielmoralesp
Twitter:
@danielmpbp

2024-12-31

How does Ruby File Management Works?

Sometimes we'll need to deal with file management with Ruby. For instance, you receive a .txt file from your Project Manager (PM) and you have to read what’s inside. Other times you have to write something there. Cases like this can happen with different types of files, like .csv, .pdf, .xls, or .txt among others. 

This is a common task in Ruby and you have to deal with them accordingly. Previously we talked about Ruby Gems, there are plenty of them who help us to deal with all this kind of file formats. Later we’ll be studying those formats in detail, but for now we’ll be seeing just .txt file formats and using the built-in “File” Ruby class. Before that we have to understand what’s I/O

I/O
In computing, input/output (I/O, or informally io or IO) is the communication between an information processing system, such as a computer, and the outside world, possibly a human or another information processing system. Inputs are the signals or data received by the system and outputs are the signals or data sent from it. The term can also be used as part of an action; to "perform I/O" is to perform an input or output operation. For more info about I/O in ruby please go ahead here

Ruby provides a whole set of I/O-related methods implemented in the Kernel module. All the I/O methods are derived from the class IO. The class IO provides all the basic methods, such as read, write, gets, puts, readline, getc, and printf.

So far, we’ve seen a couple of them like the “puts” command to print something on the console or the “gets” command to  receive user inputs. What we’re going to see now is the “read” and “write” commands. But after that let’s check the class “File” in Ruby

A “File” is an abstraction of any file object accessible by the program and is closely associated with class IO. So, let’s check how it works

TXT Files (text files)
A text file is a kind of computer file that is structured as a sequence of lines of text. A text file exists stored as data within a computer file system. 

On modern operating systems such as Microsoft Windows and Unix-like systems, text files do not contain any special EOF (end of line) character, because file systems on those operating systems keep track of the file size in bytes. Most text files need to have end-of-line delimiters, which are done in a few different ways depending on the operating system. Some operating systems with record-oriented file systems may not use new line delimiters and will primarily store text files with lines separated as fixed or variable length records.

So, as you can see there is a lot of attention under the delimiters. Basically if you end a line of text, it will be followed by an “enter” or a “line space” and that will be the End of Line. And that's how text files store data (line by line) and ois the way que can create, read, edit or delete such textfile
 


Read
First we need to create a new text file under our folders that will contain the .txt file. So let’s begin

➜  blog_tutorials mkdir file_management
➜  blog_tutorials touch file_management/content.txt 
➜  blog_tutorials cd file_management 
➜  file_management ls
content.txt


Now let’s open it from our Text Editor, and start wiring something inside the text file. Let do something very simple:

content.txt
my first line
my second line
my third line



With the file created we’re ready to use the Read method from Ruby. To do this we have to know the File class in ruby. The File class in Ruby is an abstraction of any file object accessible by the program and is closely associated with class IO. But here you’re probably confused, because you could ask what's the difference between I/O Ruby Class and File Ruby Class? Really good question to ask and here is the answer: since File is a subclass of IO and it does not have the read method, when you invoke File.read, you are actually calling IO.read no difference here.

Now we can go ahead and call the “.read” method. Go to your console and access the folder “file_management” the same we created before with the command mkdir (where we have the file content.txt) and open the irb Ruby console


➜  file_management irb
2.6.8 :001 > File.read("content.txt")
 => "my first line\nmy second line\nmy third line" 
2.6.8 :002 > 




We’ve invoked the Read method from I/O through the File class in Ruby. However the output seems a bit weird, and it’s because of the End of Line. We have line breaks in your original document, so the way ruby reads and prints the result is adding \ instead of EOLs. If we want to get the same output as the original we can follow 3 basic steps:
  • - Step #1- Assign the Read output to a variable
  • - Step #2- Split the output by the line break. This split converts the string into an array with each different line of text
  • - Step #3- iterate over the array which is basically each line of text we splitted before



2.6.8 :007 > content = File.read("content.txt")
 => "my first line\nmy second line\nmy third line" 
2.6.8 :008 > lines = content.split("\n")
 => ["my first line", "my second line", "my third line"] 
2.6.8 :009 > lines.each do |line|
2.6.8 :010 >     puts line
2.6.8 :011?>   end
my first line
my second line
my third line
 => ["my first line", "my second line", "my third line"] 


As you can see the “split” method is the key here, because we choose the pattern “\n” as the rule to separate each line of text and save the result as an array of different lines of text. 

Write
Now let’s use the ”.write” method. This method doesn't need to have a file previously created. What it does for us is to check if the file exists, if so they overwrite the file with the content we pass through the method. If the file doesn't exist it creates it and adds the content. So let’s do it

2.6.8 :012 > File.write("content2.txt", "Once upon a time..")
 => 18 



And now, let’s check our text editor


We have the new file created and the text inside it. Awesome! But what happens if we try to add othe different content with the same command? 


It will overwrite the current one. BTW the 18 number refers to the amount of characters we insert in the file


And that can become a problem for us. Here is where the “Open” method comes in help. 

The “Open” method allows us to be more organized and follow the similar behavior as we were writing directly in the files as human beings. We have to first open the file, then keep it open until we write and then we close the file when we finish. If we need to add more content, we follow the same steps. So let’s do it but from our console

2.6.8 :025 > File.open("content2.txt", "a+") do |file|
2.6.8 :026 >     file.write("\nNow we add new line...")
2.6.8 :027?>   end
 => 23 


Let’s check what we did here:
  • - In the first line of code we’ve called the ”.open” method and passed 2 arguments, the first argument is the name of the file. If it exists we use it, if not we create a new one. The second argument is so important. There are different argument names we can pass here, depending on the task we want to do. For now we’re using a+ who adds the content at the end of the file. In the same line we open a ruby block and create a variable named “file” who will contain the file we opened. 
  • - Inside the ruby block we called the “.read” method with the content as the argument. We started the text of the argument with the symbol “\n” which represents a new line break. After that, and without any space, we add the text
  • - Finally we close the ruby block.

Let’s check the result


We added new text without overwriting the current one. That’s awesome!

Opening a File using Different Modes in Ruby
This is technically called I/O Open Modes. Ruby lets you open a file with different permissions (modes). You can open a file in a read only mode, write only mode, or a read-write mode. Here you have a description of each one of them


We have these 6 basic open modes. We’ve used “a+” in the last example to append data at the end of the file and with the help of the character “\n” to do a breakline. 

As always there are a lot of methods to use here with File class or IO class in ruby, and here you can find more details about them:

IO Class


File Class



Are these used in real-life scenarios?


Probably you’re asking yourself if these kinds of features are asked in real-life projects. The answer is it depends. Some solutions will need that you deal with text files some others don’t The reality is that you won’t use this too much in your day-to-day job but is really good idea to know the basics about it and for that reason we’re not going deeper here (probably in the future blog post) but if you’re required to work with file texts you know that Ruby can deal with it in an easy way. 

For now, I hope you learned a lot

Thanks for reading!
Daniel Morales