Documentation

12. Input / output

12. Input / output

FORTRAN 77's I/O is one of its strengths: a compact set of statements drives flexible, precisely formatted transfers between your variables and the outside world (§12). This chapter covers the I/O statements, units, files, and error handling; the layout language (FORMAT) is Chapter 13.

The statements

Statement Does
READ bring data in
WRITE send data out
PRINT send data out to the default output (a shorthand WRITE)
OPEN / CLOSE connect / disconnect a file to a unit
INQUIRE ask about a unit or file
BACKSPACE / ENDFILE / REWIND position a sequential file

Units

Every transfer names a unit — a non-negative integer (or * for the default) identifying where the data goes (§12.3). Two units are pre-connected by convention: unit 5 for standard input and unit 6 for standard output. * means "the default unit" (input for READ, output for WRITE).

      READ  (5, *) X            ! read from standard input
      WRITE (6, *) X            ! write to standard output
      READ  (*, *) X            ! same, using the default unit
      PRINT *, X                ! shorthand for WRITE to the default output

The control list

The parenthesized list after the statement controls the transfer (§12.8):

      READ  (UNIT=u, FMT=f, IOSTAT=ios, ERR=label, END=label) list
      WRITE (UNIT=u, FMT=f, REC=n, IOSTAT=ios, ERR=label) list
  • The first two items may be given positionally (READ (5, 10) X is UNIT=5, FMT=10); the rest are keyword form.
  • FMT= is a format: a FORMAT statement label, a character expression holding a format, or * for list-directed.
  • REC=n selects record n of a direct-access file.
  • IOSTAT=, ERR=, END= handle problems (below).

The I/O list

The data items: variables, array elements, whole arrays (expanded in storage order), and implied-DO lists:

      WRITE (6, *) A, B, V               ! V is a whole array
      WRITE (6, 20) (X(I), I = 1, N)     ! implied-DO: X(1)..X(N)
      WRITE (6, 30) ((M(I,J), J=1,3), I=1,2)   ! nested implied-DO

On output the list holds expressions; on input it holds things that can be assigned (and an earlier item can supply a later subscript: READ (5,*) N, (A(I), I=1,N)).

List-directed I/O (*)

With FMT = * you let the system choose a sensible format (§12). On input, values are separated by blanks, commas, or a slash; r*c repeats a value, r* skips, and a slash ends the read. On output each value is written in a natural width with a leading blank:

      WRITE (6, *) 1, 2.5, 'HI'      ! ->  1 2.5 HI
      READ  (5, *) A, B, C           ! reads three values, however spaced

Internal files

An internal file is a CHARACTER variable (or array) used as if it were a file — the way to format a number into a string, or parse a number out of one (§12.2.2):

      CHARACTER*10 BUF
      WRITE (BUF, '(I5)') 42         ! BUF = '   42     '  (format into a string)
      READ  (BUF, '(I5)') N          ! parse a number back out

This replaces the older ENCODE/DECODE of vendor FORTRANs with a portable, standard mechanism.

Files: OPEN, CLOSE, INQUIRE

A unit other than the pre-connected ones is connected to a file with OPEN (§12.10):

      OPEN  (UNIT=7, FILE='data.txt', STATUS='OLD', FORM='FORMATTED')
      READ  (7, *) X
      CLOSE (UNIT=7, STATUS='KEEP')

Common OPEN specifiers: FILE, STATUS (OLD/NEW/SCRATCH/UNKNOWN), ACCESS (SEQUENTIAL/DIRECT), FORM (FORMATTED/UNFORMATTED), RECL (record length, for direct access), BLANK (NULL/ZERO), plus IOSTAT/ERR. CLOSE takes STATUS (KEEP/DELETE). INQUIRE reports on a unit or file (EXIST, OPENED, NAME, ACCESS, RECL, NEXTREC, …).

  • Sequential access reads/writes records front to back; direct access addresses a record by number with REC=. A SCRATCH file is a temporary deleted on close.

Positioning a sequential file

      REWIND  7          ! back to the start
      BACKSPACE 7        ! back up one record
      ENDFILE 7          ! write an end-of-file marker

Handling end-of-file and errors

Without help, hitting end-of-file or an error on a READ stops the program. The control-list specifiers let you cope gracefully (§12.7):

  • END=label — jump to label at end-of-file.
  • ERR=label — jump to label on an error.
  • IOSTAT=ios — set integer ios after the transfer: 0 on success, negative at end-of-file, positive on an error. Test it and branch yourself.
   10 READ (5, *, IOSTAT=IOS) X
      IF (IOS .LT. 0) GO TO 900      ! end of file
      IF (IOS .GT. 0) STOP 'READ ERROR'
      ...
      GO TO 10
  900 CONTINUE

forterp notes. The nine I/O statements, list-directed I/O, internal files, direct access, and INQUIRE are implemented. IOSTAT= is set correctly on READ/WRITE (0 / negative / positive) — the IF (IOS.LT.0) / IF (IOS.GT.0) idioms work. Whether the first character of a printed record is consumed as carriage control depends on the device model, which forterp sets per dialect (F77 = terminal, so the first character is data; F66/FORTRAN-10 = line printer) — see Chapter 13.