Files

In order to read data from or write data to file, a handle must be created with the open statement at first. By default, file access is Fortran is record based. Using the read statement, the contents of a single line can be stored in a primitive or derived type variable. In order to read muliple lines sequentially, we call read inside a do loop. A file handle is closed simply with close.

open ([unit=] u, list)
Specifier Values Default Function
access direct, sequential, stream sequential Access mode. (optional)
action read, readwrite, write readwrite Kind of file access. (optional)
asynchronous no, yes no Enable asynchronous I/O. (optional)
blank null, zero null Interpretation of blanks. (optional)
decimal comma, point point Decimal edit mode. (optional)
delim apostrophe, none, quote none Delimiter for character constants. (optional)
encoding default, utf-8 default Encoding form for file. (optional)
err label Error transfer control. (optional)
file character File name or *. (optional)
form formatted, unformatted depends on access Format type. (optional)
iostat integer I/O status. (optional)
newunit integer Returns unused unit number. (optional, unless status='scratch')
pad no, yes yes Record padding. (optional)
position append, asis, rewind asis File positioning. (optional)
recl integer Record length. (optional)
status old, new, scratch, replace, unknown unknown File status at open. (optional)
unit integer Unit number. (mandatory, unless status='scratch')

A unit number must be given to the open () statement, usually, an integer ≥ 10. The unit number is used like a file handle in other programming languages. The Fortran 2008 standard introduced the newunit specifier that simply returns an unused unit number.

Reading Files

A text file data.txt with an arbitrary number of lines is given:

1,"Mediterranean Avenue",60
2,"Baltic Avenue",60
3,"Oriental Avenue",100
4,"Vermont Avenue",100
5,"Connecticut Avenue",120
6,"St. Charles Place",140

The following example can be used to read and output the file contents:

! reader.f90
program main
    use, intrinsic :: iso_fortran_env, only: error_unit
    implicit none

    character(len=*), parameter :: FILE_NAME = 'data.txt'

    character(len=100) :: street
    integer            :: i, fh, price, rc

    open (newunit=fh, action='read', file=FILE_NAME, iostat=rc)

    if (rc == 0) then
        do
            read (fh, *, iostat=rc) i, street, price                    ! Read line from file.
            if (rc /= 0) exit                                           ! Exit on error.
            print '(i1, 3a, i3)', i, ': ', trim(street), ', $', price   ! Output values.
        end do
    else
        write (error_unit, '(3a, i0)') 'Reading file "', trim(FILE_NAME), '" failed: ', rc
        stop
    end if

    close (fh)
end program main

Reading CSV Files

In order to read files containing comma-separated values (CSV), a type representing the data structure can be declared. Assume a CSV file with the following contents:

Vostok 1,1961,Yuri Gagarin
Vostok 2,1961,Gherman Titov
Vostok 3,1962,Andriyan Nikolayev
Vostok 4,1962,Pavel Popovich
Vostok 5,1963,Valery Bykovsky
Vostok 6,1963,Valentina Tereshkova

A proper type declaration for this data set may be:

type :: mission
    character(len=8)  :: name
    integer           :: year
    character(len=20) :: pilot
end type mission

type(mission) :: missions(6)

Open the CSV file and iterate over the file contents to read all lines into the array:

do i = 1, 6
    read (U, *) missions(i)
end do

The result is an array of mission type variables, whose values can be easily accessed by index and attribute:

print *, missions(1)%pilot

The file length (number of lines) has to be known in advance. Otherwise, re-allocate the array on each iteration using the intrinsic Fortran routine move_alloc() or use a linked list instead.

Writing Files

Writing to files does not differ much from reading from files. A file has to be opened for writing, using either action='write' or action='readwrite' in the open statement. One can then append data with the write statement and the output unit of the opened file. The example below writes the string Hello, World! to file hello.txt.

! writer.f90
program main
    use, intrinsic :: iso_fortran_env, only: error_unit
    implicit none

    character(len=*), parameter :: FILE_NAME = 'hello.txt'

    integer :: fh
    integer :: rc

    open (newunit=fh, action='write', file=FILE_NAME, status='replace', iostat=rc)

    if (rc == 0) then
        write (fh, '(a)') 'Hello, World!'
    else
        write (error_unit, '(3a, i0)') 'Writing to file "', trim(FILE_NAME), '" failed: ', rc
        stop
    end if

    close (fh)
end program main