SuivantPrec.Bas prec.BasNiv. sup.

10.2 External Files 

Formatted and unformatted records cannot be mixed on the same file and on most systems files designed for sequential-access are quite distinct from those created for direct-access: thus there are four different types of external file. There is no special support in Standard Fortran for any other types of file such as indexed-sequential files or name-list files.

Formatted Sequential Files 

These are often just called text files. Terminals and printers should always be treated as formatted sequential files. Data files of this type can be created in a variety of ways, for example by direct entry from the keyboard, or by using a text editor. Some Fortran systems do not allow records to be longer than a normal line of text, for example 132 characters. Unless a text file is pre-connected it must be opened with an OPEN statement, but the FORM= and ACCESS= keywords are not needed as the default values are suitable:       OPEN(UNIT=4, FILE='REPORT', STATUS='NEW') All data transfers must be carried out under format control. There are two options with files of this type: you can either provide your own format specification or use list-directed formatting.

The attraction of list-directed I/O is that the Fortran system does the work, providing simple data transfers with little programming effort. They are specified by having an asterisk as the format identifier:
       WRITE(UNIT=*, FMT=*)'Enter velocity: '
       READ(UNIT=*, FMT=*, END=999) SPEED
List-directed input is quite convenient when reading numbers from a terminal since it allows virtually "free-format" data entry. It may also be useful when reading data files where the layout is not regular enough to be handled by a format specification. List-directed output is satisfactory when used just to output a character string (as in the example above), but it produces less pleasing results when used to output numerical values since you have no control over the positioning of items on the line, the field-width, or the number of decimal digits displayed. Thus:
       WRITE(UNIT=LP, FMT=*)' Box of',N,' costs ',PRICE
will produce a record something like this:  Box of          12 costs           9.5000000 List-directed output is best avoided except to write simple messages and for diagnostic output during program development. The rules for list-directed formatting are covered in detail in section 10.10.

The alternative is to provide a format specification: this provides complete control over the data transfer. The previous example can be modified to use a format specification like this:
       WRITE(UNIT=LP, FMT=55)'Box of',N,' costs ',PRICE
 55    FORMAT(1X, A, I3, A, F6.2)
and will produce a record like this:  Box of 12 costs   9.50 The format specification is provided in this case by a FORMAT statement: its label is the format identifier in the WRITE statement. Other ways of providing format specifications are described in section 10.6.

One unusual feature of input under control of a format specification is that each line of text will appear to be padded out on the right with an indefinite number of blanks irrespective of the actual length of the data record. This means that, among other things, it is not possible to distinguish between an empty record and one filled with blanks. If numbers are read from an empty record they will simply be zero.

Unformatted Sequential Files 

Unformatted sequential files are often used as to transfer data from one program to another. They are also suitable for scratch files, i.e. those used temporarily during program execution. The only limit on the length of unformatted records is that set by the operating system; most systems allow records to contain a few thousand data items at least. The OPEN statement must specify the file format, but the default access method is "sequential". Each READ or WRITE statement transfers one unformatted record.

For example, these statements open an existing unformatted file and read two records from it:
       OPEN(UNIT=15, FILE='BIN', STATUS='OLD', FORM='UNFORMATTED')
       READ(15) HEIGHT, LENGTH, WIDTH
       READ(15) ARRAYP, ARRAYQ
BACKSPACE and REWIND statements may generally be used on all unformatted sequential files.

Unformatted Direct-access Files 

Since direct-access files are readable only by machine, it seems sensible to use unformatted records to maximise efficiency. The OPEN statement must specify ACCESS='DIRECT' and also specify the record length. Unfortunately the units used to measure the length of a record are not standardised: some systems measure them in bytes, others in numerical storage units, i.e. the number of real or integer variables a record can hold (see section 5.1). This is a minor obstacle to portability and means that you may need to know how many bytes your machine uses for each numerical storage unit, although this is just about the only place in Fortran where this is necessary. Most systems will allow you to open an existing file only if the record length is the same as that used when the file was created.

Each READ and WRITE statement transfers exactly one record and must specify the number of that record: an integer value from one upwards. The record length must not be greater than that declared in the OPEN statement; if an output record is not completely filled the remainder is undefined.

To illustrate how direct-access files can be used, here is a complete program which allows a very simple data-base, such as a set of stock records, to be examined. Assuming that the record length is measured in numerical storage units of 4 bytes, the required record length in this case can be computed as follows:
NAME1 CHARACTER*10 variable10 chars = 10 bytes.
STOCK1 INTEGER variable 1 unit = 4 bytes
PRICE 1 REAL variable 1 unit = 4 bytes
The total record length is 18 bytes or 5 numerical storage units (rounding up to the next integer).
       PROGRAM DBASE1
       INTEGER STOCK, NERR
       REAL PRICE
       CHARACTER NAME*10
 *Assume record length in storage units holding 4 chars each.
       OPEN(UNIT=1, FILE='STOCKS', STATUS='OLD',
      $ ACCESS='DIRECT', RECL=5)
 100   CONTINUE
 *Ask user for part number which will be used as record number.
       WRITE(UNIT=*,FMT=*)'Enter part number (or zero to quit):'
       READ(UNIT=*,FMT=*) NPART
       IF(NPART .LE. 0) STOP
       READ(UNIT=1, REC=NPART, IOSTAT=NERR) NAME, STOCK, PRICE
       IF(NERR .NE. 0) THEN
           WRITE(UNIT=*,FMT=*)'Unknown part number, re-enter'
           GO TO 100
       END IF
       WRITE(*,115)STOCK, NAME, PRICE
 115   FORMAT(1X,'Stock is',I4, 1X, A,' at ', F8.2, ' each')
       GO TO 100
       END
The typical output record of the program will be of the form:       Stock is 123 widgets    at   556.89 each This program could be extended fairly easily to allow the contents of the record to be updated as the stock changes.

Formatted Direct-access Files 

Formatted direct-access files are slightly more portable than the unformatted form because their record length is always measured in characters. Otherwise there is little to be said for them. The OPEN statement must specify both ACCESS='DIRECT' and FORM='FORMATTED' and each READ and WRITE statement must contain both format and record-number identifiers. List-directed transfers are not permitted. If the format specification requires more than one record to be used, these additional records follow on sequentially from that specified by REC=. It is an error to try to read beyond the end of a record, but an incompletely filled record will be padded out with blanks.

SuivantPrec.Bas prec.HautNiv. sup.