Fortran/io

It is often useful, in Fortran and other languages, to specify where, and how you want something to print or be read. Fortran offers many commands and formatting specifications which can serve these purposes. In the following sections we will be considering the I/O operations (, ,  ,  ,  ,  ,  ,  ,  ,   and  ) and I/O formatting. In Fortran 2008, a significant addition has been the ability to extend the basic facilities with user-defined routines to output derived types including those that are themselves composed of other derived types.

Together these commands form a very powerful assembly of facilities for reading and writing formatted and unformatted files with sequential, direct or asynchronous access. Indeed, the options can look bewildering at first. However, the basic operations are simple enough but they are backed up by the power and flexibility to read or write almost any file.

However, it is worth mentioning, at this stage, what Fortran cannot do simply and directly from a language-defined perspective: Fortran will not address a file defined by a URL, files must be available locally or on a mapped network drive or equivalent. Similarly, Fortran does not natively support XML, except that XML is simple ASCII text so it can be read easily but parsing it out is down to the programmer! The Fortran language knows nothing about computer graphics; you are not going to find a language-defined draw command. Fortran will happily open and read a jpg file but there is no language-defined method of displaying the file as a picture; a suitable external library will have to be used. Finally, Fortran does not have any language-defined mouse operations or touch screen gestures.

Introduction
Modern Fortran has a rich vocabulary for I/O operations. These operations can generally be used on the screen and keyboard, external files and internal files. In recent versions of Fortran, the syntax of these commands has been rationalized but most of the original syntax has been retained for backwards compatibility. I/O operations are notoriously error-prone and Fortran now supports a unified mechanism for identifying and processing errors.

Print
This is the classic "Hello World" operation, but is rarely used in production code. is one of two formatted output operations and it is also much simpler that the  statement. The main purpose of the  statement is to print to the screen (standard output unit) and it has no options for file output. The general form is:

Both  and   are optional and the   can be explicit or list-directed (as indicated by  ), and being optional can take the   format. The list is a comma separated list of literals or intrinsic type variables. So here are some examples:

Note that  is just about the only I/O operation that still does not support   and   clauses, and for this reason alone should not be used in new code except for temporary output and debugging. has no explicit mechanism for printing user-defined types and this is another reason for not using it in production code.

I/O Channels & Files
In the example on  shown above, the   statement is automatically pre-connected to the standard output device also known as the computer screen. However, in general, Fortran requires a two stage process to connect code to external files. First we have to connect the file to a Fortran channel (manually identified by a positive integer or automatically assigned a negative value): the  command, and then we can   and   to the now open channel. and  operations to a channel that is not open, results in an error; there is no language-specified buffering until the relevant channel is opened. Once an I/O operation is complete we can  the connection between the file and the Fortran channel. If a Fortran program terminates before a channel is closed to a file, Fortran will usually close the channel without significant loss of data.

The state of availability of Fortran channels can be ascertained through one form of the  command. The  command can also be used to determine the existence and other properties of a file before it is connected to a Fortran channel.

Fortran I/O to internal files does not require a pre-connection process. Fortran input from the keyboard and output to the screen is automatically pre-connected on a special channel (*). Compiler vendors are free to assign a channel number to these standard I/O devices and the user can determine which channel numbers have been used via the intrinsic module.

Open
This is the command required to establish a connection between an external file and a Fortran channel. The  command can be used to create a new file or connect to existing files. Subsequent I/O to the file, once open, is made via this channel number. The  command has options to ensure that the file already exists or does not already exist, to ensure that it is used only for input, or only for output, or for both. The expected format of the file can be specified in the  command and errors can be trapped. The full syntax of the command can appear to be rather complicated, but generally any one call to  uses only a small subset of all the available options.

The  command originated when external files were usually card images. can now specify that the connection to a file be fixed-format, asynchronous, a binary stream and many combinations of these. It is worth remembering that I/O is a major source of potential coding errors and where critical data are read they should be written again to confirm correct processing.

The value of the Fortran channel number has global scope within any one image of a Fortran program. Even if an integer variable is used to open a channel and that variable has very limited scope, the actual channel number is effectively ubiquitous. This needs to be considered at design time because one module can open, say, channel 10, and another module can close channel 10 without any use association between them. For this reason, in large programs, it is often the case that a single module is used to control all file i/o operations so that a clear and obvious "open - read/write - close" chain can be maintained.

Finally, as usual with Fortran, there are options and clauses which are retained for legacy purposes which should not be used in new code.

Open Command Syntax
Where [] indicate optional sections and  is a comma separated list of options. In the above, u is a scalar integer expression or equivalent and is required unless the  option is specified. (Bad luck: we cannot open more than one file in one  statement). Technically, u is called the external file unit number, or channel number for short.

Common Options
where nu is a default integer variable. This allows the processor to select the channel number and, to avoid conflicts with legacy code, a negative value (not -1) will be selected that does not conflict with any current unit number in use. This is the form that should be used in all new code.

where ios is a default integer variable which will be set to zero if the open statement does not detect an error, but will be set to a positive value is an error does occur, and the exact value is vendor dependent. Although technically an option, this is a highly recommended option for all  commands. If this option is not present (and the  option is not present, see below) the program will stop if there is an error. The presence of this option confers on the programmer the responsibility to check the value returned and have the program act accordingly.

where iom is a scalar character variable of default kind. Again, although technically an option, this is a highly recommended option for all  commands in new code. The length of the message is error and vendor specific and may require some trial and error.

where fln is a default character variable, literal or expression which specifies the name of the external file. The file name can be a fully qualified path or a local filename. If the path points to a file on a network drive the drive must be preconnected and there is no language defined way of making this connection. (Except that we can always resort to )

where stn is also a default character variable, literal or expression which must evaluate (case independently) to one of 'old', 'new', 'replace', 'scratch' or 'unknown'. 'old' requires the file to exist and is typically used when the purpose of the open statement is to allow a file to be read. 'new' and 'replace' require the presence of the  option described above, and 'new' requires the file to not exist, and 'replace' allows the file to already exist but if it does it will be overwritten. 'scratch' is special in that the  option must not be used and the file created cannot be kept on subsequent execution of a   command. 'scratch' is typically used for the temporary warehousing of large data structures to a hard disk or similar mass storage. If 'unknown' is specified this is also the default if the  option is not given, and the file status becomes vendor and system dependent, i.e. a manual will have to be consulted.

where act is a default kind character expression, variable or value that evaluates to 'read', 'write' or 'readwrite'. Somewhat amazingly, the default is processor dependent, so the manual will have to be consulted. If 'read' is specified, the file is to be regarded as read only and attempt to execute,   or   statements on this channel will result in errors. Similarly if 'write' is specified, the file is to be regarded as write only and attempts to execute a  statement will result in an error. When 'write' is specified some other statements may result in an error in a processor dependent manner (e.g. ).

Less Common Options
where acl is a character expression, variable or literal that evaluates to either 'sequential', 'direct' or 'stream'. When opening a file that already exists, this value must correspond to an allowed value which is usually the value given when the file was created. The default for a new file is 'sequential'. 'stream' access is new at Fortran 2008 and provides some compatibility with C binary stream files. The other really important feature of 'stream' access is that a file can be positioned for write and part of the file overwritten without changing the rest of the file. For formatted stream files the  function will return the relevant new line characters in the character variable nl.

where rcl is an integer expression, variable or literal that must evaluate to a positive value. For a file to be opened for direct access this 'option' is required and must specify the length of each record. For sequential files it is optional and can be used to specify the maximum length of a record. For a file that already exists, the value or rcl must correspond to the value used to create the file. In any case, the value of rcl must also be allowed by the underlying operating system.

where frm is a character expression, variable or literal that evaluates to either 'formatted' or 'unformatted'. This option can often be omitted since the default is 'formatted' for sequential access and 'unformatted' for direct access.

where blk is a character expression, variable or literal that provides the value 'null' or 'zero' for formatted i/o only. See bn and bz formats below.

where psn is a character expression, variable or literal that evaluates to 'asis', 'rewind' or 'append' and applies only when the access method is sequential. The default value is 'asis'. When opened, a new file is always positioned at its initial point but for existing files, the user has the option of where to position the current position.s

Options to Avoid
There is much legacy code out there and this section describes features that are still legal but which should be considered for replacement, and certainly not used in new code.

where eno is a literal integer label number. If an error occurs in the processing of the  statement the program will transfer control to the statement with label number eno. The presence of the err= option caused the program to continue if there was an error. This option should now be replaced with  and. (It is legal to specify both  and , but without either the program will stop if an error occurs processing the   statement.)

where nu is a default integer expression, variable or literal value which must be positive and which must not coincide with any unit already in use. If this option is placed first in the list of options the "unit=" can be omitted. This was very widely used and should now be replaced with. In very old code, nu was a fixed value and the programmer had to ensure that it did not clash with other channels in use at the same time. More recently, the  statement can be used to select a unit number not already in use, but this could not guard against a subsequent   statement trying to use a fixed value already in use. This is why the  option, and only the   option, is allowed to specify a negative value for the channel number.

Read
The  statement is a statement which reads from the specified input in the specified form, a variable. For example,

will create an integer memory cell for, and then it will read a value with the default formatting from the default input and store it in. The first  in   signifies where the value should be read from. The second  specifies the format the user wants the number read with. Let us first discuss the format strings available. In Fortran we have at our disposal many format strings with which we may specify how we want numbers, or character strings to appear on the screen. For fixed point reals: ; w is the total number of spaces allotted for the number, and d is the number of decimal places. The decimal place always takes up one position. For example,

The details of the I/O formatting e.g. '(F5.2)' will be described below

Inquire
The  statement has two basic forms: "  by unit" and "  by file" and both are very useful and well worth getting to know. There is a more obscure form called " by length" which is useful for checking the unformatted record length of potential output in order to decide what record length may be required, or whether a file with an already defined record length can cope with a given output.

Inquire by length
This rather more obscure version of the  command is used to obtain the length of an unformatted record required to contain a given form of output and hence allow the user to either check or specify the length of a record required.

Close
The  command releases the connection between a file and a Fortran channel. In the process, and depending on how the file was opened, the file can be saved or discarded. The general form of the  command is as follows: Where  is a default integer expression, variable or literal value that evaluates to the number of the channel to close, and   is optional. The options available in the option list are as follows:

where  is a default integer variable which will return with the value 0 if the   command is executed correctly. If an error occurs the return value will be positive and a message describing the error will be provided via the  option described below.

where  is a literal integer label number. If an error occurs in the processing of the  statement, the program will transfer control to the statement with label number eno. The presence of the err= option caused the program to continue if there was an error. This option should now be replaced with  and. (It is legal to specify both  and , but without either the program will stop if an error occurs processing the   statement.)

where  is a scalar character variable of default kind. Again, although technically an option, this is a highly recommended option for all  commands in new code. The length of the message is error and vendor specific and may require some trial and error.

Close errors
It is perhaps counter intuitive, but Fortran does not consider attempting to CLOSE a channel that is already closed to be an error. Like  and , the errors   will report are effectively operating system errors. For example,  with   on a channel which is already closed is an error especially if the file no longer exists. Similarly, Fortran will report an error if a file created as 'scratch' is closed with  because the only option for scratch files is. These limitations are predicated on the  (and  ) clause being used to allow the user to program for graceful termination when necessary, and not to obtain a full report on the performance of a   command.

List-Directed Formatting
We describe explicit formatting below but it is immediately clear that there is a whole "language within a language" so Fortran provides a short cut, or language-defined format guessing. It turns out that this default formatting is very close to a comma separated variable (CSV) processor for input. List-directed I/O is specified by a  clause, but the fmt clause is optional and can be replaced with just *.

Explicit Formatting
Fortran has a rich, but very terse, language for controlling the formatting of I/O operations. The format commands can be placed in an explicit  statement or they can be placed within a clause of the relevant READ or WRITE statement either literally or stored in a   variable.