Welcome to a tutorial on File IO in Elixir.
in general, File IO is an integral part of any programming language, because it allows the language to interact with the files on the file system. We will learn about two modules of File IO (Path and File).
The path module is a very small module typically considered a helper module for filesystem operations. It functions majorly in the File module expect paths as arguments, and those paths will be regular binaries.
Also, the Path module provides facilities for working with such paths. Therefore, making use of functions from the Path module as opposed to just manipulating binaries is preferred since the Path module takes care of different operating systems transparently. However, it is observed that Elixir will automatically convert slashes (/) into backslashes () on Windows when performing file operations. Check out the example below.
IO.puts(Path.join("foo", "bar"))
The output is:
foo/bar
In addition, the path module provides so many methods. These methods are commonly used when performing lots of file manipulation operations. You can check them out yourself.
The file module contains functions that make it possible to open files as IO devices. However, files are opened in binary mode, by default, and require developers to use the specific IO.binread and IO.binwrite functions from the IO module. Check out the example below on to create a file called newfile and then write some data to it.
{:ok, file} = File.read("newfile", [:write])
# Pattern matching to store returned stream
IO.binwrite(file, "This will be written to the file")
Now, when we go to open the file we just wrote into, the content will be displayed in the following way:
This will be written to the file
Let’s learn how to use the file module in the session below.
The code below can be used to open a file.
{:ok, file} = File.open("newfile")
file = File.open!("newfile")
Below are highlights of the difference between the File.open function and the File.open!() function.
Note that, this is the pattern followed in all of the file module functions we are going to discuss in this tutorial.
Also, we can specify the modes in which we want to open this file. Thus, to open a file as read-only and in utf-8 encoding mode, we can use the code below.
file = File.open!("newfile", [:read, :utf8])
There are two ways to write to files. The first one involves using the write function from the File module. This is shown below.
File.write("newfile", "Hello")
Note that, the above should not be used when making multiple writes to the same file. Every time this function is called, a file descriptor is opened and a new process is spawned to write to the file. Therefore, if you are doing multiple writes in a loop, open the file via File.open and write to it using the methods in the IO module. Check out the example below to understand better.
#Open the file in read, write and utf8 modes.
file = File.open!("newfile_2", [:read, :utf8, :write])
#Write to this "io_device" using standard IO functions
IO.puts(file, "Random text")
Also, you can use other IO module methods such as IO.write and IO.binwrite to write to files opened as io_device.
There are two ways to read from files. The first one is to use the read function from the File module. This is shown below.
IO.puts(File.read("newfile"))
Now, when running this code, a tuple is obtained with the first element as :ok and the second one as the contents of newfile
Also, we can use the File.read! function to get the contents of the files returned to us.
Anytime we open a file using the File.open function, after we are done using it, we should close it using the File.close function:
File.close(file)