File Input/Output

Sequential unformatted files include record markers (compiler-specific); access="stream" gives a plain byte stream readable from C/Python (numpy.fromfile).

18.1 OPEN, WRITE, READ, CLOSE

program file_io
  implicit none
  integer :: u, ios, i
  real :: x, y
  character(len=256) :: line, msg

  ! Write a text file
  open(newunit=u, file="data.txt", status="replace", action="write", iostat=ios, iomsg=msg)
  if (ios /= 0) error stop trim(msg)
  do i = 1, 5
    write(u, '(i3, 2f10.4)') i, real(i), sqrt(real(i))
  end do
  close(u)

  ! Read it back until end of file
  open(newunit=u, file="data.txt", status="old", action="read")
  do
    read(u, *, iostat=ios) i, x, y
    if (ios /= 0) exit                ! iostat_end (negative) at EOF
    print *, i, x, y
  end do
  close(u)

  ! Read whole lines
  open(newunit=u, file="data.txt", action="read")
  do
    read(u, '(a)', iostat=ios) line
    if (is_iostat_end(ios)) exit
    print *, trim(line)
  end do
  close(u)
end program file_io

18.2 OPEN specifiers

let the runtime choose a free unit number (F2008) "old", "new", "replace", "scratch", "unknown" "read", "write", "readwrite" "asis", "rewind", "append" "sequential", "direct", "stream" "formatted", "unformatted" record length (direct access) iostat=, iomsg=

18.3 Unformatted (binary) & stream I/O

Sequential unformatted files include record markers (compiler-specific); access="stream" gives a plain byte stream readable from C/Python (numpy.fromfile).

real(dp) :: big(1000, 1000)
open(newunit=u, file="matrix.bin", form="unformatted", access="stream", status="replace")
write(u) shape(big), big                 ! raw bytes, fast and compact
close(u)

open(newunit=u, file="matrix.bin", form="unformatted", access="stream", status="old")
read(u) dims, big
close(u)

18.4 Direct access

open(newunit=u, file="records.dat", access="direct", recl=8, form="unformatted")
write(u, rec=5) 3.14_dp
read(u, rec=5) x

18.5 Other I/O statements

inquire(file="data.txt", exist=exists, size=nbytes)
inquire(unit=u, opened=is_open, name=fname)
inquire(iolength=reclen) x, y              ! record length for direct access
rewind(u); backspace(u); endfile(u); flush(u)
write(*, '(a)', advance='no') "Prompt> "   ! non-advancing I/O

18.6 NAMELIST — simple configuration files

integer :: nsteps = 100
real :: dt = 0.01
character(len=20) :: method = "euler"
namelist /config/ nsteps, dt, method

open(newunit=u, file="input.nml", status="old")
read(u, nml=config)
close(u)
write(*, nml=config)
&config
  nsteps = 500
  dt = 0.001
  method = "rk4"
/

18.7 Asynchronous I/O

open(..., asynchronous="yes"), write(u, asynchronous="yes", id=req) data, wait(u, id=req) — overlap I/O with computation.

18.8 Scientific file formats

For large/portable datasets use NetCDF (netcdf-fortran), HDF5 (Fortran API), ADIOS2, or JSON/TOML via json-fortran, toml-f.