11. Input/Output
11.1. Format Variables
-
A format may be the value of a character expression (constant or otherwise),
or be stored in a character array, as in
-
write(6, '(i5)') x
11.2. END=, ERR=, and IOSTAT= Clauses
-
A
read
or
write
statement may contain
end=,
err=,
and
iostat=
clauses, as in
-
write(6, 101, err=20, iostat=a(4))
read(5, 101, err=20, end=30, iostat=x)
Here 5 and 6 are the
units
on which the I/O is done,
101 is the statement number of the associated format,
20 and 30 are statement numbers,
and
a
and
x
are integers.
If an error occurs during I/O,
control returns to the program at statement 20.
If the end of the file is reached,
control returns to the program at statement 30.
In any case, the variable referred to in
the
iostat=
clause is given a value when
the I/O statement finishes.
(Yes, the value is assigned to the name on the right side of the equal sign.)
This value is zero if all went well,
negative for end of file,
and some positive value for errors.
11.3. Formatted I/O
11.3.1. Character Constants
-
Character constants in formats are copied literally to the output.
Character constants cannot be read into.
-
write(6,'(i2,'' isn''''t '',i1)') 7, 4
produces
-
7 isn't 4
Here the format is the character constant
-
(i2,' isn''t ',i1)
and the character constant
-
isn't
is copied into the output.
11.3.2. Positional Editing Codes
-
t,
tl,
tr,
and
x
codes
control where the
next character is in the record.
trn
or
nx
specifies that the next character is
to the right of the current position.
tln
specifies that the next character is
to the left of the current position,
allowing parts of the record to be reconsidered.
tn
says that the next character is to be character
number in the record.
(See section 3.4 in the main text.)
-
A colon in the format terminates the I/O operation
if there are no more data items in the I/O list,
otherwise it has no effect.
In the fragment
-
x='("hello", :, " there", i4)'
write(6, x) 12
write(6, x)
the first
write
statement prints
hello there 12,
while the second only prints
hello.
11.3.4. Optional Plus Signs
-
According to the Standard,
each implementation has the option of putting
plus signs in front of non-negative
numeric output.
The
sp
format code may be used to make the optional plus
signs actually appear for all subsequent items
while the format is active.
The
ss
format code guarantees that the I/O system will not
insert the optional plus signs,
and the
s
format code restores the default behavior of
the I/O system.
(Since we never put out optional plus signs,
ss
and
s
codes have the same effect in our implementation.)
11.3.5. Blanks on Input
-
Blanks in numeric input fields,
other than leading blanks
will be ignored following a
bn
code in a format
statement,
and will be treated as zeros following a
bz
code in a format statement.
The default for a unit may be changed by using
the
open
statement.
(Blanks are ignored by default.)
11.3.6. Unrepresentable Values
-
The Standard requires that if a numeric item
cannot be represented in the form required by a format code,
the output field must be filled with asterisks.
(We think this should have been an option.)
-
There is a new integer output code,
iw.m.
It is the same as
iw,
except that there will be at least
digits in the output field,
including,
if necessary,
leading zeros.
The case i is special,
in that if the value being printed is 0,
the output field is
entirely blank.
iw.1
is the same as
iw.
11.3.8. Floating Point
-
On input, exponents may start with the letter
E, D, e, or d.
All have the same meaning.
On output we always use e.
The
e
and
d
format codes also have identical meanings.
A leading zero before the decimal point in
e
output
without a scale factor is optional with the
implementation.
(We do not print it.)
There is a
gw.d
format code which is the same as
ew.d
and
fw.d
on input,
but which chooses
f
or
e
formats for output depending.
on the size of the number and of .
11.3.9. ``A'' Format Code
-
A codes are used for character values.
aw
use a field width of ,
while a plain
a
uses the length of the character item.
11.4. Standard Units
-
There are default formatted input and output units.
The statement
-
read 10, a, b
reads from the standard unit using format statement 10.
The default unit may be explicitly specified by an asterisk, as in
-
read(*, 10) a,b
Similarly, the standard output units is specified by a
print
statement or an asterisk unit:
-
print 10
write(*, 10)
11.5. List-Directed Formatting
-
List-directed I/O is a
kind of free form input for sequential I/O.
It is invoked by using an asterisk as the
format identifier, as in
-
read(6, *) a,b,c
-
On input,
values are separated by strings of blanks
and possibly a comma.
Values,
except for character strings,
cannot contain blanks.
End of record counts as a blank,
except in character strings,
where it is ignored.
Complex constants are given as two real constants
separated by a comma and enclosed in parentheses.
A null input field,
such as between two consecutive commas,
means the corresponding variable in the
I/O list is not changed.
Values may be preceded by repetition counts,
as in
-
4*(3.,2.) 2*, 4*'hello'
which stands for 4 complex constants, 2 null values,
and 4 string constants.
-
For output, suitable formats are chosen for
each item.
The values of character strings are printed;
they are not enclosed in quotes, so they cannot be read back
using list-directed input.
11.6. Direct I/O
-
A file connected for direct access consists of
a set of equal-sized records each of which is
uniquely identified by a positive integer.
The records may be written or read in any order,
using direct access I/O statements.
-
Direct access
read
and
write
statements
have an extra argument,
rec=,
which gives the record number to be read or written.
-
read(2, rec=13, err=20) (a(i), i=1, 203)
reads the thirteenth record into the array
a.
-
The size of the records must be given by an
open
statement
(see below).
Direct access files may be connected for either formatted
or unformatted I/O.
11.7. Internal Files
-
Internal files are character string objects,
such as variables or substrings,
or arrays of type character.
In the former cases there is only a single record
in the file,
in the latter case each array element is a record.
The Standard includes only sequential
formatted I/O on internal files.
(I/O is not a very precise term to use here,
but internal files are dealt with using
read
and
write).
There is no list-directed I/O on internal files.
Internal files are used by giving the name of the
character object in place of the unit number, as in
-
character*80 x
read(5,"(a)") x
read(x,"(i3,i4)") n1,n2
which reads a card image into
x
and then reads
two integers from the front of it.
A sequential
read
or
write
always starts at the beginning
of an internal file.
-
(We also support a compatible extension, direct I/O on internal files.
This is like direct I/O on external files,
except that the number of records in the file cannot be
changed.)
11.8. OPEN, CLOSE, and INQUIRE Statements
-
These statements are used to connect and disconnect
units and files,
and to gather information about units and files.
-
The
open
statement is used to connect a file with a
unit,
or to alter some properties of the connection.
The following is a minimal example.
-
open(1, file='fort.junk')
open
takes a variety of arguments with meanings described below.
-
\(IP .nr IP +1
unit= a small non-negative integer which is the unit to
which the file is to be connected.
We allow,
at the time of this writing,
0 through 9.
If this parameter is the first one in the
open
statement,
the
unit=
can be omitted.
\(IP .nr IP +1
iostat= is the same as in
read
or
write.
\(IP .nr IP +1
err= is the same as in
read
or
write.
\(IP .nr IP +1
file= a character expression,
which when stripped of trailing blanks,
is the name of the file to be connected to the unit.
The filename should not be given if the
status=scratch.
\(IP .nr IP +1
status= one of
old,
new,
scratch,
or
unknown.
If this parameter is not given,
unknown
is assumed.
If
scratch
is given,
a temporary file will be created.
Temporary files are destroyed at the end of execution.
If
new
is given,
the file will be created if it doesn't exist,
or truncated if it does.
The meaning of
unknown
is processor dependent;
our system treats it as synonymous with
old.
\(IP .nr IP +1
access= sequential
or
direct,
depending on whether the file is
to be opened for sequential or direct I/O.
\(IP .nr IP +1
form= formatted
or
unformatted.
\(IP .nr IP +1
recl= a positive integer specifying the record length of
the direct access file being opened.
We measure all record lengths in bytes.
On
UNIXsystems a record length of 1 has the special meaning explained
in section 5.1 of the text.
\(IP .nr IP +1
blank= null
or
zero.
This parameter has meaning only for formatted I/O.
The default value is
null.
zero
means that blanks,
other than leading blanks,
in numeric input fields are to be treated as zeros.
-
Opening a new file on a unit which is already connected
has the effect of first closing the old file.
-
close
severs the connection between a unit and a file.
The unit number must be given.
The optional parameters are
iostat=
and
err=
with
their usual meanings,
and
status=
either
keep
or
delete.
Scratch files cannot be kept,
otherwise
keep
is the default.
delete
means the file will be removed.
A simple example is
-
close(3, err=17)
-
The
inquire
statement gives information about
a unit
(``inquire by unit'')
or a file (``inquire by file'').
Simple examples are:
-
inquire(unit=3, namexx)
inquire(file='junk', number=n, exist=l)
-
\(IP .nr IP +1
file= a character variable specifies the file the
inquire
is about.
Trailing blanks in the file name are ignored.
\(IP .nr IP +1
unit= an integer variable specifies the unit the
inquire
is about.
Exactly one of
file=
or
unit=
must be used.
\(IP .nr IP +1
iostat=, err= are as before.
\(IP .nr IP +1
exist= a logical variable.
The logical variable is set to
.true.
if the file or unit
exists and is set to
.false.
otherwise.
\(IP .nr IP +1
opened= a logical variable.
The logical variable is set to
.true.
if the file
is connected to a unit or if the unit is connected
to a file,
and it is set to
.false.
otherwise.
\(IP .nr IP +1
number= an integer variable to which is assigned the
number of the unit connected to the file,
if any.
\(IP .nr IP +1
named= a logical variable to which is assigned
.true.
if
the file has a name,
or
.false.
otherwise.
\(IP .nr IP +1
name= a character variable to which is assigned the name
of the file (inquire by file) or the name of the
file connected to the unit (inquire by unit).
The name will be the full name of the file.
\(IP .nr IP +1
access= a character variable to which will be assigned
the value
'sequential'
if the connection is for
sequential I/O,
'direct'
if the connection is for direct I/O.
The value becomes undefined if there is no connection.
\(IP .nr IP +1
sequential= a character variable to which is assigned the
value
'yes'
if the file could be connected for
sequential I/O,
'no'
if the file could not be connected for sequential I/O,
and
'unknown'
if we can't tell.
\(IP .nr IP +1
direct= a character variable to which is assigned the value
'yes'
if the file could be connected for direct I/O,
if the file could not be connected for direct
I/O,
and
'unknown'
if we can't tell.
\(IP .nr IP +1
form= a character variable to which is assigned the value
'formatted'
if the file is connected for formatted I/O,
or
'unformatted'
if the file is connected for unformatted
I/O.
\(IP .nr IP +1
formatted= a character variable to which is assigned the value
'yes'
if the file could be connected for formatted I/O,
'no'
if the file could not be connected for formatted I/O,
and
'unknown'
if we can't tell.
\(IP .nr IP +1
unformatted= a character variable to which is assigned the value
'yes'
if
the file could be connected for unformatted I/O,
'no'
if the file could not be connected for unformatted I/O,
and
'unknown'
if we can't tell.
\(IP .nr IP +1
recl= an integer variable to which is assigned the record length
of the records in the file if the file is connected
for direct access.
\(IP .nr IP +1
nextrec= an integer variable to which is assigned one more
than the number of the the last record read from a file connected
for direct access.
\(IP .nr IP +1
blank= a character variable to which is assigned the value
'null'
if null blank control is in effect for the file
connected for formatted I/O,
'zero'
if blanks are being converted to zeros and
the file is connected for formatted I/O.
The gentle reader
will remember that the people who wrote the standard
probably weren't thinking of his needs.
Here is an example.
The declarations are omitted.
-
open(1, file="/dev/console")
On a
UNIXsystem this statement opens the console for formatted sequential
I/O.
An
inquire
statement for either unit 1 or file "/dev/console"
would reveal that the file exists, is connected to unit 1,
has a name, namely "/dev/console",
is opened for sequential I/O,
could be connected for sequential I/O,
could not be connected for direct I/O (can't seek),
is connected for formatted I/O,
could be connected for formatted I/O,
could not be connected for unformatted I/O
(can't seek),
has neither a record length nor a next record number,
and is ignoring blanks in numeric fields.
In the
UNIXsystem environment,
the only way to discover what permissions you have
for a file is to open it and try to read and write it.
The
err=
parameter will return system error numbers.
The
inquire
statement does not give a way of determining permissions.