Sage-Code Laboratory

File Handling

Fortran is designed to work with data files. So it has statements for handling files. It can open a files, read and write data into the files and search in files back and forward. This is necesary to analyze data, create logs and reports, load or export data files.



Data input/output operations are tightly related to data types. Usually input/output can be from console or from data fields. Data files can be on disk or tape. There are 3 statement for performing I/O.

These operations require format specification, and can output a list of variables, constants or expressions. The arguments are separated by comma.

Logic Unit

Data is transferred between the program and devices or files through a Fortran logical unit. Logical units are identified in an I/O statement by a logical unit number, a nonnegative integer from 0 to the maximum 4-byte integer value (2,147,483,647).

Standard I/O

The character "*" can appear as a logical unit identifier. The asterisk stands for standard input file when it appears in a READ statement; it stands for standard output file when it appears in a WRITE or PRINT statement.

Implicit Units

Unit numbers below 10 are reserved unit numbers for system ussage. You should use > 10 unit numbers when you create or open your own files. These are reserved:

Read & Print

Reading standard input and printing is done using "*". In next example we use them both. Usually the standard input is the console and the application become interactive. I have run this example with and yo can see the results in console.

example: input.f95
program main
  implicit none

  real :: pi
  real :: radius
  real :: height
  real :: area
  real :: volume

  pi = 3.1415927

  print *, 'Cylinder radius:'
  read(*,*) radius

  print *, 'Cylinder height:'
  read(*,*) height

  area = pi * radius**2.0
  volume = area * height

  print *, 'radius is: ', radius
  print *, 'height is: ', height
  print *, 'base area: ', area
  print *, 'volume is: ', volume

end program
 Cylinder radius:
 Cylinder height:
 radius is:    10.0000000    
 height is:    15.0000000    
 base area:    314.159271    
 volume is:    4712.38916     

Writing to file

Fortran can output data into permanent files. If exist, a file can be open. If does not exist, a file can be created using "open" statement. When a file is open you must specify the logic unit. All other statement need the same unit ID to identify the file you are refering to.

example: report.f95
program main
  integer :: io   ! unit number
  integer :: stat ! status number
  !check if file exist and remove it
  logical :: exists
  inquire(file="report.txt", exist=exists)
  if (exists) then
    open(file="report.txt", newunit=io, iostat=stat)
    if (stat == 0) then
       close(io, status="delete", iostat=stat)  
    end if
  end if
  !create new file report.txt
  open(newunit=io, file="report.txt", &
       status="new", action="write")
  do i=1,10
      write(io, *) "row", i
  end do
end program
>cat report.txt
 row           1
 row           2
 row           3
 row           4
 row           5
 row           6
 row           7
 row           8
 row           9
 row          10

Description: In the example above we have open a file called "report.txt" and we have recreated the file. Then we have written 10 rows and then close the file. Ouside of program, we have used command "cat" that is a Bash command to list the report content.

Format specification

Data format can be simple as "*" that is handled automatically by the system and it supports many variables. Better format is a string containing a set of rule that you can create for different data types:

!fortran example
program main
  real:: r = 225.502
  integer:: i = 25
  character(len=*):: t= "Test"
  fmt='(a," ", i5.4," ", f10.5)'
  print fmt, trim(t), i, r
end program
Test  0025  225.50200

Notes: In the example above you can see 3 variables of different kind can be combined using a single format string that has inside 3 specifications separated by comma. You will get many errors until you get the format right. The format is very powerful feature in Fortran. If you learn it right you can create a report quickly from your data.

Format Rules

Rule format is a string with the following convention: It must be enclosed in round brackets like: "( ... )" or '( ... )'. The specification can hold rules and arbitrary text. The text must be enclosed in alternative quotes, "" or '' depending on outer quotes.

Format Description
"..." Inserts arbitrary characters.
Iw[.m] Read/write w characters as integer number, with optional number of leading zeros m.
Bw[.m] Read/write w characters as binary values, with optional number of leading zeros m.
Ow[.m] Read/write w characters as octal values, with optional number of leading zeros m.
Zw[.m] Read/write w characters as hexadecimal values, with optional number of leading zeros m.
Fw.d Read/write floating-point number in decimal notation, with w digits, of which d is the number of decimal places. Sign and floating point must be regarded in w. F0.d allows a variable length.
Ew.d Read/write floating-point number in exponential notation, with w characters and a mantissa of d digits..
EXw.d[Ee]Read/write real value in hexadecimal, with field width w, the number of hexadecimal digits in d, and the optional exponent e (Fortran 2018).
Dw.d Read/write Floating-point number, double precision.
A, Aw. Read/write arbitrary length string, or fixed string with w characters
Lw Read/write w characters as logical.
nX Read: Ignore the next n characters.
nX Write: Print n spaces."
Tc Puts next character at position c in line.
/ Force a line feed that makes rule o 2 rows.

Multiple Columns

The rule can be multiplied like this: nR where n is an integer number. It will create n columns having same rule R. The rule R can start with a capital letter or lowercase letter in modern Fortran. Next example show you such rule:

example: mcol.f95
!fortran example
program main
  integer :: io   ! unit number
  integer :: stat ! status number
  !check if file exist and remove it
  logical :: exists
  inquire(file="mcol.txt", exist=exists)
  if (exists) then
    open(file="mcol.txt", newunit=io, iostat=stat)
    if (stat == 0) then
       close(io, status="delete", iostat=stat)  
    end if
  end if
  !create new file mcol.txt
  open(newunit=io, file="mcol.txt", &
       status="new", action="write")
  block ! local scope
    real(8):: a,b,c,d
    call srand(2022) ! initialize
    do i=1,20
        write(io, "(a, i4.2, 4f8.4)") &
                  "row", i, a, b, c, d
    end do
  end block
end program
console: mcol.txt

>cat mcol.txt
row  01  0.0158  0.9694  0.8340  0.3906
row  02  0.2554  0.7355  0.1242  0.6645
row  03  0.5373  0.9490  0.4412  0.2599
row  04  0.2119  0.9048  0.0994  0.0538
row  05  0.0641  0.5657  0.2664  0.1550
row  06  0.1566  0.6544  0.9108  0.3426
row  07  0.9495  0.4500  0.9530  0.2241
row  08  0.1507  0.8074  0.6687  0.1644
row  09  0.6800  0.9732  0.3576  0.6896
row  10  0.1952  0.4620  0.8776  0.7148
row  11  0.5126  0.7167  0.2193  0.2855
row  12  0.3706  0.9709  0.1654  0.8778
row  13  0.4196  0.4239  0.8524  0.9736
row  14  0.7799  0.8616  0.4338  0.6776
row  15  0.7381  0.0610  0.4188  0.4611
row  16  0.2086  0.1453  0.9424  0.0846
row  17  0.9904  0.8209  0.1442  0.4619
row  18  0.3793  0.1206  0.4297  0.7354
row  19  0.2594  0.7389  0.1492  0.1095
row  20  0.6615  0.2698  0.7818  0.3536

Read next: Data Structures