File input and output

Yutaka Masuda

February 2020

Back to index.html.

File input and output

In Fortran, input and output (I/O) from/to a file has the same form as I/O from the keyboard or to the screen (physical devices). The only difference is that, for the file I/O, the source and the destination are a file, not the physical devices. Defining a file as a “device” allows you to read and write the data to and from the “device” using the read and write statements with the same edit descriptors as we have seen before. Before trying the file I/O, I encourage the readers to master the basics of print and read with edit descripter.

In this chapter, we will see how to write and read a file.

File basics

Output to text file

The following is a typical program to save some numbers to a file. This program creates a file output.txt in the current directory.

program file
   implicit none
   real :: a,b,c

   ! computation
   a = 1
   b = 2
   c = log(a+b)

   ! save the values to a file
   open(10,file='input.txt')
   write(10,*) a,b,c
   close(10)
end program file

Contrary to print, we need a couple of steps to save the values to a file.

  1. Use the open statement to connect a file name output.txt to an integer number (logical unit number). After this, all the access to the file is performed through this number.
  2. Writes 3 values to ten files using the default format.
  3. After the values are written, disconnect to the file using close.

You can check if the new file is created in the current directory where you are working. It is a text file containing human-readable characters, and it contains 3 numbers with the default format as you get by print *,a,b,c, on the screen. To short, the output to a text file is the same as the screen output except for that additional statements, open and close, are needed.

Input from text file

File reading has the same behavior as keyboard input except that the values are from a file. As file writing, you have to call open before reading a file, and close for the termination. Using the file created above, you can read 3 values from the file.

program file
   implicit none
   real :: a,b,c
   ! read the values from a file
   open(10,file='output.txt')
   read(10,*) a,b,c
   close(10)
end program file

The file output.txt should be in the same directory as the program. Otherwise, this program stops on open with an error. The read statement has at least two parameters in () with the same meaning as write. If enough values are not in the file, the read statement generates an error.

Unit number

You can use any unit number (basically, positive integer numbers) if it has not been already used as the unit number. A best practice is to use an integer variable for the unit number. See the following piece of code.

program file
   ...
   integer :: unit
   ...
   unit = 10
   open(unit,file='output.txt')
   write(unit,*) a,b,c
   close(unit)
end program file

In the Modern Fortran standard, the user does not have to choose the unit number anymore. The system can automatically assign an appropriate number through the newunit= option in open. The above example is reduced to the following code.

program file
   ...
   integer :: unit
   ...
   open(newunit=unit,file='output.txt')
   write(unit,*) a,b,c
   close(unit)
end program file

You don’t have to initialize unit because a value is assigned to unit at the open statement.

Practical text file reading and writing

Reading a file

Opening an exisitng file

If you want to make sure that a file exists when opening the file, you can put an option, status="old" in open.

   open(newunit=unit,file="input.txt",status="old")

If there is no file, the program stops with an error. You can get the error status of open using iostat= with an arbitrary integer variable.

   integer :: info
   ...
   open(newunit=unit,file="input.txt",status="old",iostat=info)

With the above statement, the program checks if there is input.txt or not. If the file is not there, it returns a negative value to the variable (info). Otherwise, it returns 0 to the variable. So, the following code catches the error.

   integer :: info
   ...
   open(newunit=unit,file="input.txt",status="old",iostat=info)
   if(info/=0) stop "No file"

The statement, status="old", make the file read-only. When you try write to this file, you should get an error.

Error status while reading the file

A text file may have multiple lines (rows), and sometimes you do not know how many rows the file has. The read statement can detect an error while reading a text file. The error status is available with the iostat= option with an arbitrary integer variable. Here is a piece of code with an arbitrary variable, info, to catch the error status.

   integer :: unit,info
   ...
   read(unit,*,iostat=info) a,b,c

In the above code, info has the status of read.

Repeated reading the data

There is a typical form to read the data from the file until the end of the file. It looks similar to read the data from the keyboard until you input particular values.

   do
      read(unit,*,iostat=info) a,b,c
      if(info<0) exit
      ...
   end do

Ignored fields

When a line has space-separated, multiple fields, but the variables cannot read all of them, and the read statement ignores the rest of them. For example, you have the following file.

  10  10  15  ABC

The following code reads the first 3 numbers but ignores the characters ABC without any errors.

   read(unit,*,iostat=info) a,b,c

In this way, while you read some numerical values in the first few fields, you can put characters in the last fields.

Writing a file

Creating a new file

When you open a file that already exists, the write statement will renew it by default. Precisely, it completely removes the existing file, and the new content is placed in the file as the first record. Be aware that there is a risk to lose the file. The following piece of code shows this behavior.

   open(newunit=unit,file="data.txt")

   ! It removes the file, and it updates the file by the value, 100.
   write(unit,*) 100

Appending data to an existing file

IF a file is already there, you can append the data to it without losing the file. You need position="append" in open to do this.

   open(newunit=unit,file="data.txt",position="append")

Using this option, the new data is added to the end of file.

Error status while reading the file

With this option, the new data is added to the end of the file.

   integer :: unit,info
   ...
   write(unit,*,iostat=info) a,b,c

The status (info) is 0 when there is no error. It is positive if there is an error with write (for example, trying to write a file in a read-only device).

No “new line”

The write statement puts a “newline” at the end of the data. To suppress the new line, use advance="no". It is useful in a file and on the screen.

   write(unit,*,advance="no") 10,20
   write(unit,*,advance="no") 30,40
   write(unit,*) 50
        10        20        30        40        50

File position

Moving a file position

When open a file, the file position is set to the beginning of the file by default. With position="append" in open, the file position is at the end of the file. Whenever you perform read or write, the file position moves to the top of the next line. There are some statements to change the file position.

Statement Description Example
backspace(unit) Move back to the previous line backspace(10)
rewind(unit) Move back to the beginning of the file rewind(10)

When to lose the file

There is an essential fact in the file I/O: you can perform both read and write to the same file by default. This fact explains when you lose a file by write. Assume that you move the position to the top of the third line in a text file by performing read twice. The file position is shown as > in the following example file.

   The first line
   The second line
>  The third line
   The fourth line

With this setting, when you perform write, the program removes all the subsequent lines at and after the third line in the file, then it writes a new line to the third line. Here is the resulting content in the file.

   The first line
   The second line
   Added line
>

When opening a file, the file position is at the top of the file; you write the data to the file, and you will lose the existing content in the file. When opening it with position=append, the position moves to the end of the file, and you can write the new line while keeping the entire file. I encourage the reader not to use both read and write in the same file unless you really need to do it.

Back to index.html.