ACCESS='STREAM'
specifier.
A stream file is either a formatted stream or an unformatted stream.
A formatted stream file is equivalent to a C text stream; this acts much like
an ordinary sequential file, except that there is no limit on the length of a
record.
Just as in C, when writing to a formatted stream, an embedded newline
character in the data causes a new record to be created.
The new intrinsic enquiry function NEW_LINE(A)
returns this character
for the kind (character set) of A
; if the character set is ASCII, this
is equal to IACHAR(10)
.
For example,
OPEN(17,FORM='formatted',ACCESS='stream',STATUS='new') WRITE(17,'(A)'), 'This is record 1.'//NEW_LINE('A')//'This is record 2.'
An unformatted stream file is equivalent to a C binary stream, and has no
record boundaries.
This makes it impossible to BACKSPACE
an unformatted stream.
Data written to an unformatted stream is transferred to the file with no
formatting, and data read from an unformatted stream is transferred directly
to the variable as it appears in the file.
When reading or writing a stream file, the POS=
specifier may be used
to specify where in the file the data is to be written.
The first character of the file is at position 1.
The POS=
specifier may also be used in an INQUIRE
statement, in
which case it returns the current position in the file.
When reading or writing a formatted stream, the POS=
in a READ
or WRITE
shall be equal to 1 (i.e. the beginning of the file) or to
a value previously discovered through INQUIRE
.
Note that unlike unformatted sequential files, writing to an unformatted stream file at a position earlier than the end of the file does not truncate the file. (However, this truncation does happen for formatted streams.)
Finally, the STREAM=
specifier has been added to the INQUIRE
statement.
This specifier takes a scalar default character variable, and assigns it the
value 'YES'
if the file may be opened for stream input/output
(i.e. with ACCESS='STREAM'
), the value 'NO'
if the file cannot be
opened for stream input/output, and the value 'UNKNOWN'
if it is not
known whether the file may be opened for stream input/output.
BLANK=
and PAD=
specifiers, which previously were only
allowed on an OPEN
statement (and INQUIRE
), are now allowed on a
READ
statement.
These change the BLANK=
or PAD=
mode for the duration of that
READ
statement only.
DECIMAL=
specifier and the DC
and DP
edit descriptors.
The DECIMAL=
specifier may appear in OPEN
, READ
,
WRITE
and INQUIRE
statements; possible values are 'POINT'
(the default) and 'COMMA'
. For an unconnected or unformatted unit,
INQUIRE
returns 'UNDEFINED'
.
The DC
edit descriptor temporarily sets the mode to
DECIMAL='COMMA'
, and the DP
edit descriptor temporarily sets the
mode to DECIMAL='POINT'
.
When the mode is DECIMAL='COMMA'
, all floating-point output will
produce a decimal comma instead of a decimal point, and all floating-point
input will expect a decimal comma.
For example,
PRINT '(1X,"Value cest ",DC,F0.2)',1.25will produce the output
Value cest 1,25
Additionally, in this mode, a comma cannot be used in list-directed input to separate items; instead, a semi-colon may be used.
DELIM=
specifier, which previously was only allowed on an
OPEN
statement (and INQUIRE
), is now allowed on a WRITE
statement.
It changes the DELIM=
mode for the duration of that WRITE
statement; note that this only has any effect if the WRITE
statement
uses list-directed or namelist output.
For example,
WRITE(*,*,DELIM='QUOTE') "That's all folks!"will produce the output
'That''s all folks!'
ENCODING=
specifier is permitted on OPEN
and
INQUIRE
statements.
Standard values for this specifier are 'UTF-8'
and the default value
of 'DEFAULT'
; the 'UTF-8'
value is only allowed on compilers
that support a Unicode character kind (see SELECTED_CHAR_KIND
).
This release of the NAG Fortran Compiler supports 'DEFAULT'
and 'ASCII'
.
IOMSG=
specifier has been added to all input/output statements.
This takes a scalar default character variable, which in the event of an error
is assigned an explanatory message.
(Note that this is only useful if the statement contains an IOSTAT=
or
ERR=
specifier, otherwise the program will be terminated on error
anyway.)
If no error occurs, the value of the variable remains unchanged.
SIGN=
specifier has been added to the OPEN
, WRITE
and
INQUIRE
statements; possible values are 'PLUS'
, 'SUPPRESS'
and 'PROCESSOR_DEFINED'
(the default).
For the NAG Fortran Compiler, SIGN='PROCESSOR_DEFINED'
has the same
effect as SIGN='SUPPRESS'
.
The effect of SIGN='PLUS'
is the same as the SP
edit descriptor,
the effect of SIGN='SUPPRESS'
is the same as the SS
edit
descriptor, and the effect of SIGN='PROCESSOR_DEFINED'
is the same
as the S
edit descriptor.
IS_IOSTAT_END
and IS_IOSTAT_EOR
test IOSTAT=
return values, determining whether a value indicates an
end-of-file condition or an end-of-record condition.
These are equivalent to testing the IOSTAT=
return value against the
named constants IOSTAT_END
and IOSTAT_EOR
respectively; these
constants are available through the ISO_FORTRAN_ENV
module.
-Infinity
(or -Inf
if it will not fit) for negative infinity;
Infinity
(or Inf
if it will not fit) for positive infinity,
or +Infinity
(or +Inf
) with SP
or SIGN='PLUS'
mode;
NaN
for a NaN.
Input of IEEE infinities and NaNs is now possible; these take the same form as the output described above, except that:
READ
or WRITE
statement with that namelist
is executed.
Also, if a variable is polymorphic or has an ultimate component that is
allocatable or a pointer, it is only permitted in a namelist when it will be
processed by defined input/output (see below).
READ
or WRITE
statement.
Input/output to an external file while external file input/output is already in progress remains prohibited, except for the case of nested data transfer (see “Defined input/output”).
ASYNCHRONOUS=
specifier on OPEN
, READ
, WRITE
and
INQUIRE
, the ID=
specifier on READ
, WRITE
and
INQUIRE
, and the PENDING=
specifier on INQUIRE
.
Except for the INQUIRE
statement, the ASYNCHRONOUS=
specifier
takes a scalar default character expression; this must evaluate either to
'YES'
or 'NO'
, treating lowercase the same as uppercase.
In the READ
and WRITE
statements, this character expression
must be a constant expression, and the statement must refer to an external file
whose connection allows asynchronous input/output;
if ASYNCHRONOUS='YES'
is specified, the data transfer may occur
asynchronously.
In the OPEN
statement, this specifier determines whether asynchronous
data transfer is allowed for that file: the default setting is 'NO'
.
For the INQUIRE
statement, the ASYNCHRONOUS=
specifier takes a
scalar default character variable, and sets it to 'YES'
if the file is
currently connected for asynchronous input/output, 'NO'
if the current
connection does not allow asynchronous input/output and 'UNKNOWN'
if
the file is not connected.
For the READ
and WRITE
statements, the ID=
specifier takes
a scalar integer variable.
This specifier is only permitted if ASYNCHRONOUS='YES'
also appears.
The integer variable is assigned the “identifier” of the asynchronous
data transfer that the READ
or WRITE
initiates; this value can be
used in INQUIRE
and WAIT
statements to track the progress of
the asynchronous data transfer.
For the INQUIRE
statement, the ID=
specifier takes a scalar
integer expression whose value must be that returned from ID=
on a
READ
or WRITE
statement for that file, and is only permitted in
conjunction with the PENDING=
specifier.
The PENDING=
specifier takes a scalar default logical variable and
sets it to .TRUE.
if the specified asynchronous data transfer is still
underway and to .FALSE.
if it has completed.
If PENDING=
is used without ID=
, the enquiry is about all
outstanding asynchronous data transfer on that file.
After initiating an asynchronous data transfer, the variables affected must
not be referenced or defined until after the transfer is known to have
finished.
For an asynchronous WRITE
of a local variable, this means not returning
from the procedure until after ensuring the transfer is complete.
An asynchronous data transfer is known to have been finished if there is a
subsequent synchronous data transfer, an INQUIRE
statement which returns
.FALSE.
for PENDING=
, or a WAIT
statement has been
executed; in each case, for that file.
buf1
and buf2
,
alternately reading into one while processing the other, while there
is still data in the file to process (each dataset being followed by
a single logical value which indicates whether more is to come).
REAL :: buf1(n,m),buf2(n,m) LOGICAL more,stillwaiting READ (unit) buf1 DO READ (unit) more ! Note: synchronous IF (more) READ (unit,ASYNCHRONOUS='YES') buf2 CALL process(buf1) IF (.NOT.more) EXIT READ (unit) more ! Note: synchronous IF (more) READ (unit,ASYNCHRONOUS='YES') buf1 CALL process(buf2) IF (.NOT.more) EXIT END DO
Note that the synchronous READ
statements automatically
“wait” for any outstanding asynchronous data transfer to complete
before reading the logical value; this ensures that the dataset will have
finished being read into its buffer and is safe to process.
ASYNCHRONOUS
attribute [5.2]READ
or WRITE
statement with ASYNCHRONOUS='YES'
automatically gives the ASYNCHRONOUS
attribute to any variable that
appears in its input/output list, in a SIZE=
specifier, or which is
part of a namelist specified by NML=
.
This is adequate for asynchronous data transfers that initiate and complete
within a single procedure.
However, it is inadequate for transfers to/from module variables or dummy
arguments if the procedure returns while the transfer is still underway.
The ASYNCHRONOUS
attribute may be explicitly specified in a type
declaration statement or in an ASYNCHRONOUS
statement.
The latter has the syntax
ASYNCHRONOUS
[::
] variable-name [ ,
variable-name ]...
If a variable with the ASYNCHRONOUS
attribute is a dummy array and is
not an assumed-shape array or array pointer, any associated actual argument
cannot be an array section, an assumed-shape array or array pointer.
Furthermore, if a dummy argument has the ASYNCHRONOUS
attribute the
procedure must have an explicit interface.
Both of these restrictions apply whether the attribute was given explicitly or
implicitly.
WAIT
statement [5.2]WAIT
statement provides the ability to wait for an asynchronous data
transfer to finish without performing any other input/output operation.
It has the form
WAIT
( wait-spec [ ,
wait-spec ]... )
UNIT =
file-unit-number
END =
label
EOR =
label
ERR =
label
ID =
scalar-integer-variable
IOMSG =
scalar-default-character-variable
IOSTAT =
scalar-integer-variable
The UNIT=
specifier must appear, but the ‘UNIT =
’ may be
omitted if it is the first specifier in the list.
The ID=
specifier takes a scalar integer expression whose value must be
that returned from ID=
on a READ
or WRITE
statement for
the file; if the ID=
specifier does not appear the WAIT
statement
refers to all pending asynchronous data transfer for that file.
On completion of execution of the WAIT
statement the specified
asynchronous data transfers have been completed.
If the specified file is not open for asynchronous input/output or is not
connected, the WAIT
statement has no effect (it is not an error unless
the ID=
specifier was used with an invalid value).
Here is an example of using the WAIT
statement.
REAL array(1000,1000,10),xferid(10) ! Start reading each segment of the array DO i=1,10 READ (unit,id=xfer(i)) array(:,:,i) END DO ... ! Now process each segment of the array DO i=1,10 WAIT (unit,id=xfer(i)) CALL process(array(:,:,i) END DO
P
)
and a repeat count (e.g. the ‘3
’ in 3E12.2
), is now
optional.
This trivial extension was part of Fortran 66 that was removed in Fortran 77,
and reinstated in Fortran 2003.
FLUSH
statement causes the data written to a specified
file to be made available to other processes, or causes data placed in that
file by another process to become available to the program.
The syntax of the FLUSH
statement is similar to the BACKSPACE
,
ENDFILE
and REWIND
statements, being one of the two possibilities
FLUSH
file-unit-number
FLUSH (
flush-spec [ , flush-spec ]... )
UNIT =
file-unit-number
IOSTAT =
scalar-integer-variable
IOMSG =
scalar-default-character-variable
ERR =
label
The UNIT=
specifier must appear, but the ‘UNIT =
’ may be
omitted if it is the first flush-spec in the list.
Here is an example of the use of a FLUSH
statement.
WRITE (pipe) my_data FLUSH (pipe)
READ(FORMATTED)
, READ(UNFORMATTED)
,
WRITE(FORMATTED)
and WRITE(UNFORMATTED)
provide the ability
to replace normal input/output processing for an item of derived type.
In the case of formatted input/output, the replacement will occur for
list-directed formatting, namelist formatting, and for an explicit format
with the DT
edit descriptor: it does not affect any other edit
descriptors in an explicit format.
Using defined input/output, it is possible to perform input/output on
derived types containing pointer components and allocatable components,
since the user-defined procedure will be handling it.
Here is a type definition with defined input/output procedures.
TYPE tree TYPE(tree_node),POINTER :: first CONTAINS PROCEDURE :: fmtread=>tree_fmtread PROCEDURE :: fmtwrite=>tree_fmtwrite GENERIC,PUBLIC :: READ(formatted)=>fmtread, WRITE(formatted)=>fmtwrite END TYPE
Given the above type definition,
whenever a TYPE(tree)
object is an effective item in a formatted
input/output list,
the module procedure tree_fmtread
will be called (in a READ
statement) or the module procedure tree_fmtwrite
will be called
(in a WRITE
statement) to perform the input or output of that object.
Note that a generic interface block may also be used to declare procedures
for defined input/output; this is the only option for sequence or
BIND(C)
types but is not recommended for extensible types.
The procedures associated with each input/output generic identifier must have
the same characteristics as the ones listed below, where type-declaration
is CLASS(
derived-type-spec)
for an extensible type and
TYPE(
derived-type-spec)
for a sequence or BIND(C)
type. Note that if the derived type has any length type parameters, they
must be “assumed” (specified as ‘*
’).
SUBROUTINE formatted_read(var,unit,iotype,vlist,iostat,iomsg)
type-declaration,INTENT(INOUT) :: var
INTEGER,INTENT(IN) :: unit
CHARACTER(*),INTENT(IN) :: iotype
INTEGER,INTENT(IN) :: vlist(:)
INTEGER,INTENT(OUT) :: iostat
CHARACTER(*),INTENT(INOUT) :: iomsg
SUBROUTINE unformatted_read(var,unit,iostat,iomsg)
type-declaration,INTENT(INOUT) :: var
INTEGER,INTENT(IN) :: unit
INTEGER,INTENT(OUT) :: iostat
CHARACTER(*),INTENT(INOUT) :: iomsg
SUBROUTINE formatted_write(var,unit,iotype,vlist,iostat,iomsg)
type-declaration,INTENT(IN) :: var
INTEGER,INTENT(IN) :: unit
CHARACTER(*),INTENT(IN) :: iotype
INTEGER,INTENT(IN) :: vlist(:)
INTEGER,INTENT(OUT) :: iostat
CHARACTER(*),INTENT(INOUT) :: iomsg
SUBROUTINE unformatted_write(var,unit,iostat,iomsg)
type-declaration,INTENT(IN) :: var
INTEGER,INTENT(IN) :: unit
INTEGER,INTENT(OUT) :: iostat
CHARACTER(*),INTENT(INOUT) :: iomsg
In each procedure, unit
is either a normal unit number if the parent
input/output statement used a normal unit number, a negative number if the
parent input/output statement is for an internal file, or a processor-dependent
number (which might be negative) for the ‘*
’ unit.
The iostat
argument must be assigned a value before returning from
the defined input/output procedure: either zero to indicate success, the
negative number IOSTAT_EOR
(from the intrinsic module
ISO_FORTRAN_ENV
) to signal an end-of-record condition, the negative
number IOSTAT_END
to signal an end-of-file condition, or a positive
number to indicate an error condition.
The iomsg
argument must be left alone if no error occurred, and
must be assigned an explanatory message if iostat
is set to a nonzero
value.
For the formatted input/output procedures, the iotype
argument will be
set to ‘LISTDIRECTED
’ if list-directed formatting is being done,
‘NAMELIST
’ if namelist formatting is being done, and
‘DT
’ concatenated with the character-literal if the
DT
edit descriptor is being processed.
The vlist
argument contains the list of values in the DT
edit
descriptor if present, and is otherwise a zero-sized array.
Note that the syntax of the DT
edit descriptor is:
DT
[ character-literal ] [ (
value [ ,
value ]... )
]
DT
edit descriptors: it is up to the user-defined
procedure to interpret what they might mean.
During execution of a defined input/output procedure, there must be no
input/output for an external unit (other than for the unit
argument),
but input/output for internal files is permitted.
No file positioning commands are permitted.
For unformatted input/output, all input/output occurs within the current
record, no matter how many separate data transfer statements are executed by
the procedure; that is, file positioning both before and after “nested”
data transfer is suppressed.
For formatted input/output, this effect is approximately equivalent to the
nested data transfer statements being considered to be nonadvancing;
explicit record termination (using the slash (/
) edit descriptor, or
transmission of newline characters to a stream file) is effective, and record
termination may be performed by a nested list-directed or namelist input/output
statement.
If unit
is associated with an external file (i.e. non-negative, or
equal to one of the constants ERROR_UNIT
, INPUT_UNIT
or
OUTPUT_UNIT
from the intrinsic module ISO_FORTRAN_ENV
),
the current settings for the pad mode, sign mode, etc., can be discovered by
using INQUIRE
with PAD=
, SIGN=
, etc. on the unit
argument.
If unit
is negative (associated with an internal file), INQUIRE
will raise the error condition IOSTAT_INQUIRE_INTERNAL_UNIT
.
Finally, defined input/output is not compatible with asynchronous input/output; all input/output statements involved with defined input/output must be synchronous.