FORTRAN: Input/Output (I/O)

SIMPLE I/O: LIST-DIRECTED

The simplest form of the I/O statement is the list-directed form which is represented by:
          READ(*,*) item1, item2, item3...

          WRITE(*,*) item1, item2, item3...
where ITEMx = a variable, a constant or math expression
     Example:  WRITE(*,*)  'ALPHA=', ALPHA
The first asterisk (*) means the input comes from the keyboard in a READ statement and goes to the screen in a WRITE statement. The second asterisk (*) means the computer decides how the I/O elements should look based on the TYPE of data in the input/output list. This is sometimes called "FREE-FORMAT".

NOTES ON LIST-DIRECTED I/O

SPACES may be inserted between components of the statement to add clarity.

The READ statement causes the program to PAUSE and allow you to enter values. The program will not continue until all values have been entered.

Separate values with SPACES when typing data into the program with a READ operation. Make sure you press the ENTER key.

Insert a WRITE statement to PROMPT yourself for input just before a READ statement. This statement should tell the user WHAT to enter.

GENERAL FORM OF I/O STATEMENTS

The general form of the FORTRAN I/O statements allow data transfer to FILES, TAPE, PRINTER and other devices as well as the TERMINAL. The general form is:
          WRITE(unit#, format, options) item1, item 2,...

          READ(unit#, format, options) item1, item2,...
NOTE: We will restrict our use to TERMINAL and FILE I/O. Typically, you transfer data files to/from tape, diskette, and printer by using UNIX (or DOS on PCs) commands, rather than a Fortran program reading or writing directly from/to the device.

In this form, PARENTHESES are used to enclose information about the UNIT, the FORMAT (if any) and other options.

Again, SPACES may be used to add clarity to the statement.

The input and output lists (item1, item2,...) are composed of constants, variables or expressions, separated by COMMAS.

UNIT NUMBER

The UNIT is a number which has an association with a particular device. The device can be the TERMINAL or a FILE (or something else too). The UNIT is an INTEGER or INTEGER EXPRESSION, generally between 1-30.

Standard FORTRAN reserves two UNIT numbers for I/O to user. They are:

     UNIT = 5   for INPUT from the keyboard with the READ statement

     UNIT = 6   for OUTPUT to the screen with the WRITE statement

Most versions of FORTRAN will also let you use the ASTERISK (*) for I/O to the TERMINAL. The asterisk can be used with both the READ and WRITE statements, thus there is no need to remember whether 5 or 6 is for input or output.

When I/O is to a file you must ASSOCIATE a UNIT number (which you choose) with the FILENAME. Use any unit number other than 5 and 6. On some computers, some unit numbers are reserved for use by the computer operating system.

The association of the unit number and filename occurs when the OPEN statement is executed.

          OPEN(UNIT=n, FILE='filename', options...)
This statement associates UNIT n with the file mentioned. All subsequent READs or WRITEs using unit n will be to or from this file.

MISCELLANEOUS FILE I/O NOTES

When doing I/O to a FILE, each READ statement inputs data from a NEW LINE and each WRITE statement outputs data on a NEW LINE. Most files are SEQUENTIALLY organized.

You can't easily go back up in the file, but you can REWIND the file with: REWIND unit_number

When you are finished with the file, you may CLOSE it with: close(10) or close(unit=10) (This is optional.)

FORMAT IDENTIFIER

The FORMAT IDENTIFIER as used in a WRITE or READ statement generally has one of two forms;
  1. An asterisk (*), indicates LIST-DIRECTED or "free format".
  2. A LABEL designates a FORMAT statement which specifies the format to use.
For simple I/O, the * is used as we have already discussed. When you want to FORMAT your I/O, you will generally use method 2. - The FORMAT statement is a list of FORMAT DESCRIPTORS separated by commas which describe what each FIELD of the output should look like. Example:
      WRITE(*,10) 'USING', L2, 'AREA =', AREA
 10   FORMAT(1X, A5, 2X, I3, 4X, A6, 2X, F6.2)

In a format statement, there is a one-to-one correspondence with the items in the I/O list, with the exception of certain positional descriptors; X, T, /.

The FORMAT statement is defined only once (for each label referenced) in the program but may be used by any number of I/O statements.

FORMAT DESCRIPTORS

- The elements in the I/O list must agree in TYPE with the FORMAT DESCRIPTOR being used.

- There are a dozen or so descriptors, The most commonly used are:

     Descriptor          Use                           

     rIw                 Integer data
     rFw.d               Real data in decimal notation
     rEw.d               Real data in scientific notation
     Aw                  Character data
     'x...x'             Character strings
     
     nX                  Horizontal spacing (skip spaces)
     /                   Vertical spacing (skip lines)
     Tc                  Tab
                                                       
     Where:
          w  = positive integer specifying FIELD WIDTH
                    r  = positive integer REPEAT COUNT
                    d  = non-negative integer specifying number of
               digits to display to right of decimal.
                    x  = any character
                    n  = positive integer specifying number of columns
                    c  = positive integer representing column number
NOTES ON DESCRIPTORS:

- Values for I, F, and E descriptors will be right justified.

- You must leave enough space for negative sign in the field width for I, E, F, and for decimal point for E, F and for exponent for E.

- When using the E descriptor, the number will be NORMALIZED. This means the number is shifted over so that the first digit is in the tenths position. A leading zero and decimal are always present and a minus sign, if needed. The exponent always requires 4 spaces; E, the sign and 2 digits.

- If you overflow the space allotted to a descriptor, it will print out asterisks (at RUN TIME) in the field space.

- Character data (A) is also right-justified but if it overflows the allotted space it is left-most truncated.

- The first character of each line of output is used to control the vertical spacing. Use 1X to give normal spacing.

MORE COMPLICATED EXAMPLES:

1.  Format identifier

     Given:    REAL ROOT1, ROOT2

     1.   Unformatted or "free format" output:  All three are
          equivalent 
   
          Print*, root1, root2
          Write (6,*) root1, root2
          Write (6,*) 'Roots are:' root1, root2

     2.   Formatted write statements:

          Write (6,100) root1, root2                   
     100  format (1x, 'The Roots Are: ', F5.1,1x,F5.1)
     
     output: The Roots Are: 123.5 789.1
                                                  
     3.  Write(6,'(',The Roots Are: ', 2F5.1)') root1,root2
                                      

     4.  Define character*5 FRMT
               FRMT = '2F5.1'
               write(6,FRMT) root1, root2

2.  Format Descriptors
               
     Integer:  Iw   examples: NUM1 = 123, NUM2 = 456, NUM3 =9
 
               write(6,15) NUM1, NUM2, NUM3
          15   format (1x,I3,1x,I3,1x,I3)  
          
          output:  123 456   9
                  ^   ^   ^^^
               write(6,18) NUM1, NUM2, NUM3
          18   format (1x,3(I2,1x))  
          
          output:  *** ***  ***    Note: If the number is too large
                  ^   ^   ^^    for #spaces allotted, *** are printed. 
     Reals:

          REAL NUMBER1, NUMBER2
          NUMBER1 = -123.5678
          NUMBER2 = -23456.89

        A.  F format (decimal)  Fw.d   d=# places to right of decimal 

            w-d > or =  2    (to include the decimal pt and +/- sign)
     
            NUMBER1 needs format F9.4 
            NUMBER2 needs format F9.2 

        B.  E format -- good for 1) large or small numbers
                                 2) don't know the size of number
                                             
            Ew.d    w - d > or = 7:  need at least 7 places for: 
                         e-03  -- 4 places
                         +/-   -- 1 place
                         0.    -- 2 places

            NUMBER1 needs format E14.7  -0.1235678E+03
            NUMBER2 need foprmat E14.7  -0.2345689E+05

        C.  G-format        G10,3       chooses between E & F format                                     depending on the size of the 
                                        number
        
        D.  D-format     Dw.d      same as E, but for Double Precision
                         D10.3
              1.473D-05

     Character Variables:

          CHARACTER*10   NAME
          REAL SCORE1, SCORE2

          A-format       Aw        w = # characters
     
          read(10,100) NAME, SCORE1, SCORE2
     100  format(A10,1x,f6.1,1x,f6.2)

     read this one line from input file, unit=10
     JORDAN____ __98.4 __75.5 

          write(20,150) NAME
     150  format(1x,'Last name = ', A10)

     output file (unit=20) line is:

      Last name = JORDAN____            writes out left justified

     If we write NAME in A5 format

      Last name = JORDA            truncated: not enough characters

     * When reading in "free format" for a character string, your
     input needs single quotes around it.

                     read*, name
     keyboard input: 'JORDAN'

     * When reading a character string using a format statement, you
     do not need the single quotes.

                     read(*,50) name
               50    format(A10)
     keyboard input: JORDAN         no quotes!!

3.  Control of Horizontal Spacing.

    1.  nX  skips n spaces
            read (10,150) INTEGER1, INTEGER2
        150 format (I3, 12x, I3)
                             skips everything in between

    2.  Tabs!     Tc      c = column number       Great for tables!!
               
        format (1x, F7.2, T12, F7.1, T24, I6)
                                
                            starts in Column 12

4.  File Types:  Sequential:  lines of data or records are written in                               a sequence and must be read in that
    (Chapter 11)              sequence.
                       
                              If you want to ignore 4 lines and then                           read 5th line . . . 
                       
                              Must READ all 4 lines first, then start                               with 5th line.                                                           NO WAY TO SKIP to 5th line.

        Direct-access files:  Records have specified Record Length                             (RECL).  Each record can be accessed                             individually
                                You can skip to the 5th record. 

5.  Open Statements  p.518
     
          Open (unit=10, file='mydata', status='old')

          status = old, new, unknown

          You can use a character variable name, for example: 

          character*30 file1  
          file1= '/home/usr6/mr2020/lab4.data'
          open (unit=10, file=file1, status='old', readonly)
          
          The readonly option will not allow you to write to unit=10.
          This protects your file from accidentally being overwritten.

          To write to files: 
          open(unit=20,file='Lab4.output',status='new')
          
          If status='new' and then you rerun the program, the file 
          Lab4.output already exists from the last time you ran the
          program, so the program stops!

6.  Close Statements

          Close (unit=10) or Close (10)

7.  Read Statement 

-    There are three OPTIONS which are useful when READing data from a
     file, using the READ command.  They are:

          END = label    Specifies a label to branch (jump) to if an
                         END-OF-FILE (EOF) is reached (READing past
                         the end of file).
          
          Example:  read(10,130,end=300) a,b,c
             130    format(3(f7.2,1x))

                    When the end-of-file, EOF, is encountered, control
                    of the program jumps to line 300.  Typically, this
                    is used in a "read data loop", which continues
                    reading one new line at a time until EOF is found. 
                    The jump to line 300 is your only way out of the
                    loop.

          ERR = label    Specifies a label to branch to if some ERRor
                         is encountered in the I/O.

          Example:  READ(10,140,err=225) a, b, c
             140    format(f7.2,2x,f10.5,3x,e12.7)

                    When a read error is encountered, the program
                    jumps to line 225 and continues executing the
                    program from there.  Typically, you jump to a
                    section of your program that will notify you, the
                    user, that an error has occurred.  This does not
                    tell you WHICH type of error occurred.

          IOSTAT =  integer variable    Variable is assigned an
                    integer value to describe the success or error of
                    your READ statement.

                    Integer values:

                    - Zero, means the input data was read without
                    error.

                    - Negative value, means the end-of-file (EOF) mark
                    was read, which signifies the end of the input
                    data file.

                    - Positive value, means there was an error during
                    the read execution.  The positive value indicates
                    the type of error, as defined by the computer
                    operating system.

          Example:  read(10,150,iostat=k) a, b, c
             150    format(f7.2,2x,f10.5,3x,e12.7)

              k = 0 means there was no error, nor was EOF encountered.
              k = -1 means EOF was encountered.
              k = 2  refers to the operating system read error
                     "type"=2.8.  Write Statement  p. 528

Output options:  1. PRINT Command prints to the screen only!  There 
                 are wonderful options of using PRINT (format
                 specification), but it only goes to the screen!

                 2. WRITE Command writes to any user-specified "UNIT". 
                    A "unit" can be the screen (unit=6) or any open file.

                    "Write" is a more flexible command.  All the       
                    format statement options described for "print"  
                    work with "write".

                    If a user wants to write to a file, the user must                               specify:  1.  filename
                              2.  unit number

                    The "OPEN" command opens the named file and
                    assigns the unit number.  So when data is written
                    to the file, it is referred to with the "WRITE"
                    command by unit number, rather than filename.

                    Example:  filename = 'lab3.output'
                              unit number = 10

                    to write:
                              WRITE (10,100) temp, pres, density
                                             
                              unit #        format statement number

               In this course, we'll emphasize using the WRITE Command


Control Characters:  These affect the printer.  You must write data or
                     any output to a file you intend to printout (hard
                     copy) differently than you would write to data 
                     file to be read in by another program.  When I 
                     write to a file I later intend to print out, I
                     use the 1x option (skips 1 space).

                100  format (1x, 'temp = ', f5.1, 1x, 'pres = ', f6.1)