File input and output
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.
- Use the
open
statement to connect a file nameoutput.txt
to an integer number (logical unit number). After this, all the access to the file is performed through this number. - Writes 3 values to ten files using the default format.
- 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
.
info
is 0 when there is no error.info
is negative if there is no more data in the file.info
is positive if there are some errors (e.g., the data in the file does not match the variables).
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.