IRIX 6.5 » Books » Developer »
MIPSpro Fortran 90 Programmer's I/O Guide
(document number: 007-3695-006 / published: 2002-11-19)
table of contents | additional info | download find in page
Chapter 2. Standard Fortran I/O
The Fortran standard describes program statements that you can
use to transfer data between external media (external files) or between internal
files and internal storage. It describes auxiliary input/output (I/O) statements
that can be used to change the position in the external file or to write an
endfile record. It also describes auxiliary I/O statements that describe properties
of the connection to a file or that inquire about the properties of that connection.
The Fortran standard specifies the form of the
input data that a Fortran program processes and the form of output data resulting
from a Fortran program. It does not specifically describe the physical properties
of I/O records, files, and units. This section provides a general overview
of files, records, and units.
Standard
Fortran has two types of files: external and internal. An external
file is any file that is associated with a unit number. An
internal file is a character variable that is used as the unit
specifier in a READ or WRITE statement.
A unit is a means of referring
to an external file. A unit is connected or linked to a file through the
OPEN statement in standard Fortran. An external unit identifier
refers to an external file and an internal file identifier refers to an internal
file. See “Fortran Unit Identifiers”, for more information about
unit identifiers.
A file can have a name that can be specified through
the FILE= specifier in a Fortran OPEN
statement. If no explicit OPEN statement exists to connect
a file to a unit, and if assign(1) was not
used, the I/O library uses a form of the unit number as the file name.
Internal
files provide a means of transferring and converting text stored in character
variables. An internal file must be a character variable or character array.
If the file is a variable, the file can contain only one record. If the file
is a character array, each element within the array is a record. On output,
the record is filled with blanks if the number of characters written to a
record is less than the length of the record. An internal file is always positioned
at the beginning of the first record prior to data transfer. Internal files
can contain only formatted records.
When reading and writing to an internal file, only sequential
formatted data transfer statements that do not specify list-directed formatting
may be used. Only sequential formatted READ and
WRITE statements may specify an internal file.
In standard Fortran, one external unit may be connected to a file. SGI
allows more than one external unit to be connected to the standard input,
standard output, or standard error files if the files were assigned with the
assign -D command. More than one external unit can be connected
to a terminal.
External
files have properties of form, access, and position as described in the following
text. You can specify these properties explicitly by using an OPEN
statement on the file. The Fortran standard provides specific default
values for these properties.
Form (formatted or unformatted): external
files can contain formatted or unformatted records. Formatted records are
read or written by formatted I/O data transfer statements. Unformatted records
are accessed through unformatted I/O data transfer statements. If the default
does not match the form needed, you can specify the form by using an
OPEN statement.
File access (sequential or direct access):
external files can be accessed through sequential or direct access methods.
The file access method is determined when the file is connected to a unit.
Sequential access does not require an explicit
open of a file by using an OPEN statement.
When connected for sequential access, the external file has the following
properties: The records of the file are either
all formatted or unformatted, except that the last record of the file may
be an endfile record.
The records of the file must not be read or written
by direct-access I/O statements when the file is opened for sequential access.
If the file is created with sequential access,
the records are stored in the order in which they are written (that is, sequentially).
To use sequential access on a file that was created as a formatted direct-access
file, open the file as sequential. To use sequential access on a file that
was created as an unformatted direct-access file, open the file as sequential,
and use the assign command on the file as follows:
The assign command is required to specify the type
of file structure. The I/O libraries need this information to access the file
correctly.
Buffer I/O files are unformatted sequential access files.
Direct access does require an explicit open
of a file by using an OPEN statement. If a file is accessed
through a sequential access READ or WRITE
statement, the I/O library implicitly opens the file. During an explicit or
implicit open of a file, the I/O library tries to access information generated
by the assign(1) command for the file.
Direct access can be faster than sequential
access when a program must access a set of records in a nonsequential manner.
When connected for direct access, an external file has the following
properties: The records of the file are either
all formatted or all unformatted. If the file can be accessed as a sequential
file, the endfile record is not considered part of the file when it is connected
for direct access. Some sequential files do not contain a physical endfile
record.
The records of the file must not be read or written
by sequential-access I/O statements while the file is opened for direct access.
All records of the file have the same length, which
is specified in the RECL specifier of the OPEN
statement.
Records do not have to be read or written in the
order of their record numbers.
The records of the file must not be read or written
using list-directed or namelist formatting.
The record number (a positive integer) uniquely
identifies each record.
If all of the records in the file are the same length and if the file
is opened as direct access, a formatted sequential-access file can be accessed
as a formatted direct-access file if the direct access file is assigned a
text structure (with assign -s text).
Unformatted sequential-access files can be accessed as unformatted direct-access
files if all of the records are the same length and if the file is opened
as direct access, but only if the sequential-access file was created with
an unblocked file structure. The following assign
commands create these file structures: assign -s unblocked ...
assign -s u ...
assign -F system ... |
For more information about the assign environment
and about default file structures, see Chapter 6, “The assign Environment”.
File position: a file connected to a
unit has a position property, which can be either an
initial point or a terminal point. The initial point
of a file is the position just before the first record, and the
terminal point is the position just after the last record. If
a file is positioned within a record, that record is considered to be the
current record; otherwise, there is no current record.
During an I/O data transfer statement, the file can be positioned within
a record as each individual input/output list (iolist)
item is processed. The use of a dollar sign ($) or a backslash
(\) as a carriage control edit descriptor in a format may cause a file to
be positioned within a record.
In standard Fortran, the end-of-file (EOF) record is a special record
in a sequential access file; it denotes the last record of a file. A file
can be positioned after an EOF, but only CLOSE,
BACKSPACE, or REWIND statements are then allowed
on the file in standard Fortran. Other I/O operations are allowed after an
EOF to provide multiple-file I/O if a file is assigned to certain devices
or is assigned with a certain file structure.
A Fortran unit identifier is required for Fortran
READ or WRITE statements to uniquely identify
the file. A unit identifier can be one of the following: An integer variable or expression whose value is greater than
or equal to 0. Each integer unit identifier i is
associated with the fort.i
file, which may exist (except as noted in the following text). For example,
unit 10 is associated with the fort.10 file in the current
directory.
An asterisk (*) is allowed only on
READ and WRITE statements. It identifies a particular
file that is connected for formatted, sequential access. On READ
statements, an asterisk refers to unit 100 (standard input). On
WRITE statements, an asterisk refers to unit 101 (standard output).
Certain
Fortran I/O statements have an implied unit number. The PRINT
statement always refers to unit 101 (standard output), and the outmoded
PUNCH statement always refers to unit 102 (standard error).
Fortran INQUIRE and CLOSE statements
may refer to any valid or invalid unit number (if referring to an invalid
unit number, no error is returned). All other Fortran I/O statements may refer
only to valid unit numbers. For the purposes of an executing Fortran program,
all unit numbers in use or available for use by that program are valid; that
is, they exist. All unit numbers not available for use are not valid; that
is, they do not exist.
Valid unit numbers are all nonnegative numbers except 100 through
102. Unit numbers 0, 5, and 6 are associated with the standard error, standard
input, and standard output files; any unit can also refer to a pipe. All other
valid unit numbers are associated with the fort.
i file, or with the file name implied in a Hollerith unit number.
Use the INQUIRE statement to check the validity (existence)
of any unit number prior to using it, as in the following example: logical UNITOK, UNITOP...
inquire (unit=I,exist=UNITOK,opened=UNITOP)
if (UNITOK .and. .not. UNITOP) then
open (unit = I, ...)
endif |
All valid units are initially closed. A unit is connected to a file
as the result of one of three methods of opening a file or a unit: An implicit open
occurs when the first reference to a unit number is an I/O statement
other than OPEN, CLOSE, INQUIRE
, BACKSPACE, ENDFILE, or
REWIND. The following example shows an implicit open:
If unit number 4 is not open, the WRITE
statement causes it to be connected to the associated file
fort.4, unless overridden by an assign command
that references unit 4.
The BACKSPACE, ENDFILE, and
REWIND statements do not perform an implicit OPEN.
If the unit is not connected to a file, the requested operation is ignored.
An
explicit unnamed open occurs when the first reference to a unit
number is an OPEN statement without a FILE
specifier. The following example shows an explicit unnamed open: OPEN (7, FORM='UNFORMATTED') |
If unit number 7 is not open, the OPEN
statement causes it to be connected to the associated file fort.7
, unless an assign(1) command that
references unit 7 overrides the default file name.
An
explicit named open occurs when the first reference to a unit
number is an OPEN statement with a FILE
specifier. The following is an example:
If unit number 9 is not open, the OPEN
statement causes it to be connected to file blue, unless
overridden by an assign command that references the file
named blue.
Unit
numbers 100, 101, and 102 are permanently associated with the standard input,
standard output, and standard error files, respectively. These files can be
referenced on READ and WRITE statements.
A CLOSE statement on these unit numbers has no effect.
An INQUIRE statement on these unit numbers indicates they
are nonexistent (not valid).
These unit numbers exist to allow guaranteed access to the standard
input, standard output, and standard error files without regard to any unit
actions taken by an executing program. Thus, a READ or
WRITE I/O statement with an asterisk unit identifier (which is equivalent
to unit 101) or a PRINT statement always works. Nonstandard
I/O operations such as BUFFER IN and BUFFER OUT
, READMS, and WRITMS on these
units are not supported.
Fortran applications or library subroutines that must access the standard
input, standard output, and standard error files can be certain of access
by using unit numbers 100 through 102, even if the user program closes or
reuses unit numbers 0, 5, and 6.
For all unit numbers associated with the standard input, standard
output, and standard error files, the access mode and form must be sequential
and formatted. The standard input file is read only, and the standard output
and standard error files are write only. REWIND and
BACKSPACE statements are permitted on these files but
have no effect. ENDFILE statements are permitted on terminal
files unless they are read only. The ENDFILE statement
writes a logical endfile record.
The REWIND statement is not valid for any unit numbers
associated with pipes. The BACKSPACE statement is not valid
if the device on which the file exists does not support repositioning.
BACKSPACE after a logical endfile record does not require repositioning
because the endfile record is only a logical representation of an endfile
record.
The
READ statement is the data transfer input statement. The
WRITE and PRINT statements are the data transfer
output statements. If the data transfer statement contains a format specifier,
the data transfer statement is a formatted I/O statement. If the data transfer
statement does not contain a format specifier, the data transfer statement
is an unformatted I/O statement. The time required to convert input or output
data to the proper form adds to the execution time for formatted I/O statements.
Unformatted I/O maintains binary representations of the data. Very little
CPU time is required for unformatted I/O compared to formatted I/O.
In
formatted I/O, data is transferred with editing. Formatted I/O can be edit-directed,
list-directed, and namelist I/O. If the format identifier is an asterisk,
the I/O statement is a list-directed I/O statement. All other format identifiers
indicate edit-directed I/O.
Formatted I/O should be avoided when I/O performance is important. Unformatted
I/O is faster and it avoids potential inaccuracies due to conversion. However,
there are occasions when formatted I/O is necessary. The advantages for formatted
I/O are as follows: Formatted data can be interpreted by humans.
Formatted data can be readily used by programs and utilities
not written in Fortran, or otherwise unable to process Fortran unformatted
files.
Formatted data can be readily exchanged with other computer
systems where the structure of Fortran unformatted files may be different.
See the Fortran Language Reference manuals for your compiler system
for more information about formatted I/O statements.
The
format used in an edit-directed I/O statement provides information that directs
the editing between internal representation and the character strings of a
record (or sequence of records) in the file.
An example of a sequential access,
edit-directed WRITE statement follows: C Sequential edit-directed WRITE statement
C
WRITE (10,10,ERR=101,IOSTAT=IOS) 100,200
10 FORMAT (TR2,I10,1X,I10) |
An example of a sequential access, edit-directed
READ statement follows: C Sequential edit-directed READ statement
C
READ (10,11,END=99,ERR=102,IOSTAT=IOS) IVAR
11 FORMAT (BN,TR2,I10:1X,I10) |
An example of a direct access edit-directed
I/O statement follows: OPEN (11,ACCESS='DIRECT',FORM='FORMATTED',
+ RECL=24)
C
C Direct edit-directed READ and WRITE statements
C
WRITE (11,10,REC=3,ERR=103,IOSTAT=IOS) 300,400
READ (11,11,REC=3,ERR=104,IOSTAT=IOS) IVAR |
There
are four general optimization techniques that you can use to improve the efficiency
of edit-directed formatted I/O.
Procedure 2-1. Optimization technique: using single
statements Read or write as much data with a single READ/WRITE/PRINT
statement as possible. The following is an example of an inefficient way to
code a WRITE statement: DO J=1,M
DO I=1,N
WRITE (42, 100) X(I,J)
100 FORMAT (E25.15)
ENDDO
ENDDO |
It is better to write the entire array with a single WRITE
statement, as is done in the following two examples: WRITE (42, 100) ((X(I,J),I=1,N),J=1,M)
100 FORMAT (E25.15) |
or
WRITE (42, 100) X
100 FORMAT (E25.15) |
Each of these three code fragments produce exactly the same output;
although the latter two are about twice as fast as the first. Note that the
format can be used to control how much data is written per record. Also, the
last two cases are equivalent if the implied DO loops write
out the entire array, in order and without omitting any items.
Procedure 2-2. Optimization technique: using longer
records Use longer records if possible. Because a certain amount of processing
is necessary to read or write each record, it is better to write a few longer
records instead of more shorter records. For example, changing the statement
from Example 1 to Example 2 causes the resulting file to have one fifth as
many records and, more importantly, causes the program to execute faster:
Example 1: (Not recommended)
WRITE (42, 100) X
100 FORMAT (E25.15) |
Example 2: (Recommended)
WRITE (42,101) X
101 FORMAT (5E25.15) |
You must make sure that the resultant file does not contain records
that are too long for the intended application. Certain text editors and utilities,
for example, cannot process lines that are longer than a predetermined limit.
Generally lines that are 128 characters or less are safe to use in most applications.
Procedure 2-3. Optimization technique: using repeated
edit descriptors Use repeated edit descriptors whenever possible. Instead of using the
format in Example 1, use the format in Example 2 for integers which fit in
four digits (that is, less than 10000 and greater than -1000).
Example 1: (Not recommended)
Example 2: (Recommended)
Procedure 2-4. Optimization technique: using data
edit descriptors Character data should be read and written using data edit descriptors
that are the same width as the character data. For CHARACTER*
n variables, the optimal data edit descriptor is A (or A
n). For Hollerith data in INTEGER variables, the optimal data
edit descriptor is A8 (or R8).
If
the format specifier is an asterisk, list-directed formatting is specified.
The REC= specifier must not be present in the I/O statement.
In list-directed I/O, the I/O records consist of a sequence of values
separated by value separators such as commas or spaces. A tab is treated as
a space in list-directed input, except when it occurs in a character constant
that is delimited by apostrophes or quotation marks.
List-directed and namelist output of real values uses either an
F or an E format with a number of decimal digits
of precision that assures full-precision printing of the real values. This
allows formatted, list-directed, or namelist input of real values to
result later in the generation of bit-identical binary floating point representation.
Thus, a value may be written and then reread without changing the stored value.
The LISTIO_PRECISION and LISTIO_OUTPUT_STYLE
environment variables can be used to control list-directed output,
as discussed in the following paragraphs.
You can set the LISTIO_PRECISION environment
variable to control the number of digits of precision printed by list-directed
or namelist output. The following values can be assigned to LISTIO_PRECISION
: | FULL | Prints full precision (this is the default value).
| | PRECISION | Prints x or x
+1 decimal digits, where x is a value of the Fortran
95 PRECISION() intrinsic function for a given real value.
This is a smaller number of digits that usually ensures that the last decimal
digit is accurate to within 1 unit.
|
An example of a list-directed
WRITE statement follows: C Sequential list-directed WRITE statement
WRITE (10,*,ERR=101,IOSTAT=IOS) 100,200 |
An example of a list-directed
READ statement follows:
C Sequential list-directed READ statement
READ (10,*,END=99,ERR=102,IOSTAT=IOS) IVAR |
Namelist I/O is similar to list-directed
I/O, but it allows you to group variables by specifying a namelist group name.
On input, any namelist item within that list may appear in the input record
with a value to be assigned. On output, the entire namelist is written.
The namelist item name is used in the namelist input record to indicate
the namelist item to be initialized or updated. During list-directed input,
the input records must contain a value or placeholder for all items in the
input list. Namelist does not require that a value be present for each namelist
item in the namelist group.
You can specify a namelist group name in READ,
WRITE, and PRINT statements.
The following is an example of namelist I/O: NAMELIST/GRP/T,I
READ(5,GRP)
WRITE(6,GRP) |
During unformatted I/O, binary
data is transferred without editing between the current record and the entities
specified by the I/O list. Exactly one record is read or written. The unit
must be an external unit.
The following is an example
of a sequential access unformatted I/O WRITE statement: C Sequential unformatted WRITE statement
WRITE (10,ERR=101,IOSTAT=IOS) 100,200 |
The following is an example
of a sequential access unformatted I/O READ statement: C Sequential unformatted READ statement
READ (10,END=99,ERR=102,IOSTAT=IOS) IVAR |
The following is an example of a direct
access unformatted I/O statement: OPEN (11,ACCESS='DIRECT',FORM='UNFORMATTED', RECL=24)
C Direct unformatted READ and WRITE statements
WRITE (11,REC=3,ERR=103,IOSTAT=IOS) 300,400
READ (11,REC=3,ERR=103,IOSTAT=IOS) IVAR |
The auxiliary I/O statements consist of the OPEN,
CLOSE, INQUIRE, BACKSPACE,
REWIND, and ENDFILE statements. These types of
statements specify file connections, describe files, or position files. See
the Fortran Language Reference manual for your compiler system for more details
about auxiliary I/O statements.
File Connection Statements
The
OPEN and CLOSE statements specify an external
file and how to access the file.
An
OPEN statement connects an existing file to a unit, creates a file
that is preconnected, creates a file and connects it to a unit, or changes
certain specifiers of a connection between a file and a unit. The following are examples of the OPEN statement: OPEN (11,ACCESS='DIRECT',FORM='FORMATTED',RECL=24)
OPEN (10,ACCESS='SEQUENTIAL', FORM='UNFORMATTED')
OPEN (9,BLANK='NULL') |
The CLOSE statement terminates the connection of a particular
file to a unit. A unit that does not exist or has no file connected to it
may appear within a CLOSE statement; this would not affect
any files.
The INQUIRE statement describes the connection
to an external file. This statement can be executed before, during, or after
a file is connected to a unit. All values that the INQUIRE
statement assigns are current at the time that the statement is executed.
You can use the INQUIRE statement to check the properties
of a specific file or check the connection to a particular unit. The two forms
of the INQUIRE statement are INQUIRE
by file and INQUIRE by unit.
The INQUIRE
by file statement retrieves information about the properties of
a particular file.
The INQUIRE
by unit statement retrieves the name of a file connected to a specified
unit if the file is a named file. The standard input, standard output, and
standard error files are unnamed files. An INQUIRE on a
unit connected to any of these files indicates that the file is unnamed.
An INQUIRE by unit on any unit connected by using
an explicit named OPEN statement indicates that the file
is named, and returns the name that was present in the FILE=
specifier in the OPEN statement.
An INQUIRE by unit on any unit connected by using
an explicit unnamed OPEN statement, or an implicit open
may indicate that the file is named. A name is returned only if the I/O library
can ensure that a subsequent OPEN statement with a
FILE= name will connect to the same file.
File Positioning Statements
The BACKSPACE
and REWIND statements change the position of
the external file. The ENDFILE statement writes the last
record of the external file.
You cannot use file positioning statements on a file that is connected
as a direct access file. The REC= record specifier is used
for positioning in a READ or WRITE statement
on a direct access file.
The
BACKSPACE statement causes the file connected to the specified unit
to be positioned to the preceding record. The following are examples of the
BACKSPACE statement: BACKSPACE 10
BACKSPACE (11, IOSTAT=ios, ERR=100)
BACKSPACE (12, ERR=100)
BACKSPACE (13, IOSTAT=ios) |
The
ENDFILE statement writes an endfile record as the next record of
the file. The following are examples of the ENDFILE statement: ENDFILE 10
ENDFILE (11, IOSTAT=ios, ERR=100)
ENDFILE (12, ERR=100)
ENDFILE (13, IOSTAT=ios) |
The REWIND statement positions
the file at its initial point. The following are examples of the
REWIND statement: REWIND 10
REWIND (11, IOSTAT=ios, ERR=100)
REWIND (12, ERR=100)
REWIND (13, IOSTAT=ios)
REWIND (14) |
Multithreading and Standard Fortran I/O
Multithreading is the concurrent use of multiple threads of control
which operate within the same address space. Multithreading is available through
DOACROSS compiler directives and through the Pthreads interface.
Standard Fortran I/O is thread-safe. The runtime I/O library performs
all the needed locking to permit multiple threads to concurrently execute
Fortran I/O statements. The result is proper execution of all Fortran I/O
statements and the sequential execution of I/O statements issued across multiple
threads to files opened for sequential access.
MIPSpro Fortran 90 Programmer's I/O Guide
(document number: 007-3695-006 / published: 2002-11-19)
table of contents | additional info | download
Front Matter
About This Guide
Chapter 1. Introduction
Chapter 2. Standard Fortran I/O
Chapter 3. Fortran I/O Extensions
Chapter 4. Named Pipe Support
Chapter 5. System and C I/O
Chapter 6. The assign Environment
Chapter 7. File Structures
Chapter 8. Buffering
Chapter 9. Introduction to FFIO
Chapter 10. Using FFIO
Chapter 11. Foreign File Conversion
Chapter 12. I/O Optimization
Chapter 13. FFIO Layer Reference
Chapter 14. Creating a user Layer
Glossary
Index
home/search |
what's new |
help
|