Previous | Contents | Index |
This chapter describes input/output (I/O) as implemented for Compaq Fortran and discusses the following topics:
In Compaq Fortran, a logical unit is a channel through which data transfer occurs between the program and a device or file. You identify each logical unit with a logical unit number, which can be any nonnegative integer from 0 to a maximum value of 2,147,483,647 (2**31--1). For example:
READ (2,100) I,X,Y |
This READ statement specifies that data is to be entered from the device or file corresponding to logical unit 2, in the format specified by the FORMAT statement labeled 100. When opening a file, use the UNIT specifier to indicate the unit number.
Fortran 95/90 (Fortran) programs are inherently device-independent. The association between the logical unit number and the physical file can occur at run-time. Instead of changing the logical unit numbers specified in the source program, you can change this association at run time to match the needs of the program and the available resources. For example, before running the program, a script file can set the appropriate environment variable or allow the terminal user to type a directory path, file name, or both.
Use the same logical unit number specified in the OPEN statement for other I/O statements to be applied to the opened file, such as READ and WRITE.
The OPEN statement connects a unit number with an external file and allows you to explicitly specify file attributes and run-time options using OPEN statement specifiers (all files except internal files are called external files).
Certain unit numbers are preconnected to standard devices. Unit number 5 is associated with stdin , unit 6 with stdout , and unit 0 with stderr . At run time, if units 5 and 6 are specified by a record I/O statement (such as READ or WRITE) without having been explicitly opened by an OPEN statement, Compaq Fortran implicitly opens units 5, 6, and 0 and associates them with their respective operating system standard I/O files (if the corresponding FORTn environment variable is not set).
On the OPEN statement and preconnected files, see Section 7.5.
7.2 Types of I/O Statements
Table 7-1 lists the Compaq Fortran I/O statements.
Category and Statement Name | Description |
---|---|
File Connection | |
OPEN | Connects a unit number with an external file and specifies file connection characteristics. |
CLOSE | Disconnects a unit number from an external file. |
File Inquiry | |
INQUIRE | Returns information about a named file, a connection to a unit, or the length of an output item list. |
Record Position | |
BACKSPACE | Moves the record position to the beginning of the previous record (sequential access only). |
ENDFILE | Writes an end-of-file marker after the current record (sequential access only). |
REWIND | Sets the record position to the beginning of the file (sequential access only). |
Record Input | |
READ | Transfers data from an external file record or an internal file to internal storage. |
Record Output | |
WRITE | Transfers data from internal storage to an external file record or to an internal file. |
Transfers data from internal storage to stdout (standard output device). Unlike WRITE, PRINT only provides formatted sequential output and does not specify a unit number. | |
Compaq Fortran Extensions | |
ACCEPT | Reads input from stdin . Unlike READ, ACCEPT only provides formatted sequential output and does not specify a unit number. |
DELETE | Marks a record at the current record position in a relative file as deleted (direct access only). |
REWRITE | Transfers data from internal storage to an external file record at the current record position (direct access relative files only). |
UNLOCK | Releases a lock held on the current record when file sharing was requested when the file was opened. Ignored in the current version of Compaq Fortran for Tru64 UNIX and Linux Systems (see Section 7.8.2). |
TYPE | Writes record output to stdout (same as PRINT). |
DEFINE FILE | Specifies file characteristics for a direct access relative file and connects the unit number to the file, similar to an OPEN statement. Provided for compatibility with compilers before FORTRAN-77. |
FIND | Changes the record position in a direct access file. Provided for compatibility with compilers older than FORTRAN-77. |
In addition to the READ, WRITE, REWRITE, TYPE, and PRINT statements, other I/O record-related statements are limited to a specific file organization. For instance:
The file-related statements (OPEN, INQUIRE, and CLOSE) apply to any relative or sequential file.
1 Detecting deleted records is only available if the -vms option was specified when the program was compiled. For more information on the -vms option, see Section 3.98. |
Each type of record I/O statement can be coded in a variety of forms. The form you select depends on the nature of your data and how you want it treated. When opening a file, specify the form using the FORM specifier. The following are the forms of I/O statements:
Formatted, list-directed, and namelist I/O forms require translation of data from internal (binary) form within a program to external (readable character) form in the records. Consider using unformatted I/O for the following reasons:
To write data to a file using formatted, list-directed, or namelist I/O statements, specify FORM= ' FORMATTED ' when opening the file. To write data to a file using unformatted I/O statements, specify FORM= ' UNFORMATTED ' when opening the file.
Data written using formatted, list-directed, or namelist I/O statements is referred to as formatted data; data written using unformatted I/O statements is referred to as unformatted data.
When reading data from a file, you should use the same I/O statement form that was used to write the data to the file. For instance, if data was written to a file with a formatted I/O statement, you should read data from that file with a formatted I/O statement.
Although I/O statement form is usually the same for reading and writing data in a file, a program can read a file containing unformatted data (using unformatted input) and write it to a separate file containing formatted data (using formatted output). Similarly, a program can read a file containing formatted data and write it to a different file containing unformatted data.
As described in Section 7.8.2, you can access records in any sequential or relative file using sequential access. For relative files and certain (fixed-length) sequential files, you can also access records using direct access.
Table 7-2 shows the main record I/O statements, by category, that can be used in Compaq Fortran programs.
File Type, Access, and I/O Form | Available Statements |
---|---|
External file, sequential access | |
Formatted
List-Directed Namelist Unformatted |
READ, WRITE, PRINT, ACCEPT
1, TYPE
1, REWRITE
1,2
READ, WRITE, PRINT, ACCEPT 1, TYPE 1, REWRITE 1,2 READ, WRITE, PRINT, ACCEPT 1, TYPE 1, REWRITE 1,2 READ, WRITE, REWRITE 1,2 |
External file, direct access | |
Formatted
Unformatted |
READ, WRITE, and REWRITE
1,2
READ, WRITE, and REWRITE 1,2 |
Internal file 3 | |
Formatted
List-Directed Unformatted |
READ, WRITE
READ, WRITE None |
This section discusses file organization, internal and scratch files,
record type, record length, and other file characteristics.
7.4.1 File Organizations
File organization refers to the way records are physically arranged on a storage device.
Compaq Fortran supports two kinds of file organizations:
The default file organization is always ORGANIZATION= ' SEQUENTIAL ' for an OPEN statement. The organization of a file is specified by means of the ORGANIZATION specifier in the OPEN statement, as described in the Compaq Fortran Language Reference Manual.
You must store relative files on a disk device. You can store sequential files on magnetic tape or disk devices, and can use other peripheral devices, such as terminals, pipes, and line printers as sequential files.
A sequentially organized file consists of records arranged in the sequence in which they are written to the file (the first record written is the first record in the file, the second record written is the second record in the file, and so on). As a result, records can be added only at the end of the file.
Sequential files are usually read sequentially, starting with the first record in the file. Sequential files with a fixed-length record type that are stored on disk can also be accessed by relative record number (direct access).
Within a relative file are numbered positions, called cells. These cells are of fixed equal length and are consecutively numbered from 1 to n, where 1 is the first cell, and n is the last available cell in the file. Each cell either contains a single record or is empty.
Records in a relative file are accessed according to cell number. A cell number is a record's relative record number (its location relative to the beginning of the file). By specifying relative record numbers, you can directly retrieve, add, or delete records regardless of their locations (direct access). (Detecting deleted records is only available if you specified the -vms option when the program was compiled. For information on the -vms option, see Section 3.98.)
When creating a relative file, specify the RECL value to determine the
size of the fixed-length cells. Within the cells, you can store records
of varying length, as long as their size does not exceed the cell size.
7.4.2 Internal Files and Scratch Files
Compaq Fortran also supports two other types of files that are not file organizations:
When you use sequential access, you can use an internal file to reference character data in a buffer. The transfer occurs between internal storage and internal storage (unlike external files), such as between character variables and a character array.
An internal file consists of any of the following:
Instead of specifying a unit number for the READ or WRITE statement, use an internal file specifier in the form of a character scalar memory reference or a character-array name reference.
An internal file is a designated internal storage space (variable buffer) of characters that is treated as a sequential file of fixed-length records. To perform internal I/O, use formatted and list-directed sequential READ and WRITE statements. You cannot use file-related statements such as OPEN and INQUIRE on an internal file (no unit number is used).
If an internal file is made up of a single character variable, array element, or substring, that file comprises a single record whose length is the same as the length of the character variable, array element, or substring it contains. If an internal file is made up of a character array, that file comprises a sequence of records, with each record consisting of a single array element. The sequence of records in an internal file is determined by the order of subscript progression.
A record in an internal file can be read only if the character variable, array element, or substring comprising the record has been defined (a value has been assigned to the record).
Prior to each READ and WRITE statement, an internal file is always positioned at the beginning of the first record.
Scratch files are created by specifying STATUS=
'
SCRATCH
'
in an OPEN statement. By default, these temporary files are created in
(and later deleted from) the directory specified in the OPEN statement
DEFAULTFILE (if specified). To request a different directory to contain
the scratch (temporary) files, set the
TMPDIR
environment variable.
7.4.3 Record Types, Record Overhead, and Maximum Record Length
Record type refers to whether records in a file are all the same length, are of varying length, or use other conventions to define where one record ends and another begins.
You can use fixed-length and variable-length record types with sequential or relative files. You can use any of the record types with sequential files. Relative files require the fixed-length record type.
Records are stored in one of the types described in Table 7-3. When creating a new file or opening an existing file, specify one of the record types listed in this table.
Record Type | Description |
---|---|
Fixed-length |
Records in a file must
contain the same length.
You must specify the record length (RECL) when the file is opened and can obtain it before opening the file with unformatted data using a form of the INQUIRE statement (see Section 7.6.3). |
Variable-length |
Records in a file can vary in length.
This is the most portable record type across multivendor U*X platforms (such as Compaq Tru64 UNIX). Record length information is stored as control bytes at the beginning and end of each record. |
Segmented |
This pertains to a single logical record containing one or more
unformatted records of varying length, which can only be used for
unformatted sequential access.
The segmented record type is unique to Compaq Fortran products. Avoid the segmented record type when the application requires that the same file be used for programs written in languages other than Fortran and for non-Compaq platforms. However, because the segmented record type is unique to Compaq Fortran products, segmented files can be ported across Compaq Fortran platforms. |
Stream |
A stream file is not grouped into records
and uses no record delimiters.
Stream files contain character or binary data that is read or written to the extent of the variables specified. Specify CARRIAGECONTROL= ' NONE ' for stream files. |
Stream_LF and
Stream_CR |
Records
are of varying length where the line feed (LF) or the carriage return
(CR) character serve as record delimiters (LF for Stream_LF files and
CR for Stream_CR files).
Stream_LF files must not contain embedded LF characters or use CARRIAGECONTROL= ' LIST ' . Instead, specify CARRIAGECONTROL= ' NONE ' . Stream_CR files must not contain embedded CR characters. The Stream_LF record type is the usual record type for text files. |
Before you choose a record type, consider whether your application will use formatted or unformatted data. If you are using formatted data, you can choose any record type except segmented. If you are using unformatted data, avoid the stream, stream_CR, and stream_LF record types.
The segmented record type can only be used for unformatted sequential access with sequential files. You should not use segmented records for files that are read by programs written in languages other than Compaq Fortran products.
The stream, stream_CR, stream_LF, and segmented record types can be
used only with sequential files.
7.4.3.1 Portability Considerations of Record Types
Consider the following portability needs when choosing a record type:
For more information on porting Compaq OpenVMS Fortran data, see Section A.4.
The default record type (RECORDTYPE) depends on the values for the ACCESS and FORM specifiers for the OPEN statement, as described in the Compaq Fortran Language Reference Manual.
The record type of the file is not maintained as an attribute of the file. The results of using a record type other than the one used to create the file are indeterminate.
For information on choosing the most efficient record type, see Section 5.6.9.
An I/O record is a collection of fields (data items) that are logically related and are usually processed as a unit.
Unless you specify nonadvancing I/O (ADVANCE specifier), each
Compaq Fortran I/O statement transfers one record. The exceptions are
described in Section 7.8.5.
7.4.3.2 Record Overhead
Record overhead refers to bytes associated with each record that are used internally by the file system and are not available when a record is read or written. Knowing the record overhead helps when estimating the storage requirements for an application. Although the overhead bytes exist on the storage media, do not include them when specifying the record length with the RECL specifier in an OPEN statement.
The various record types each require a different number of bytes for record overhead, as described in Table 7-4.
Record Type | Organization | Record Overhead |
---|---|---|
Fixed-length | Sequential files | None. |
Fixed-length | Relative files | None if the -vms option was omitted (the default). One byte if the -vms option was specified. |
Variable-length | Sequential files | Eight bytes per record for overhead. |
Segmented | Sequential files | Four bytes per record for overhead. One additional padding byte (space) is added if the specified record size is an odd number. |
Stream | Sequential files | None required. |
Stream_CR | Sequential files | One byte per record for overhead. |
Stream_LF | Sequential files | One byte per record for overhead. |
For all but variable-length sequential records on 64-bit addressable systems, the maximum record length is 2.147 billion bytes (2,147,483,647 minus the bytes for record overhead). For variable-length sequential records on 64-bit addressable systems, the theoretical maximum record length is about 17,000 gigabytes. When considering very large record sizes, also consider limiting factors such as system virtual memory.
Other file characteristics include:
When you need to display or print formatted data that uses Fortran carriage control, consider using the fpr command as a filter through a pipe to reformat the records into operating system line printer format.
The units used for specifying record length depend on the form of the data:
To open a file, you should use a preconnected file (such as for
terminal output) or explicitly OPEN files. Although you can also
implicitly open a file, this prevents you from using the OPEN statement
to specify the file connection characteristics and other information.
7.5.1 Using Preconnected Standard I/O Files
If you do not use an OPEN statement to open logical unit 5, 6, or 0 and do not set the appropriate environment variable (FORTn), unit number 5 is associated with stdin , unit 6 with stdout , and unit 0 with stderr . At run time, Compaq Fortran implicitly opens (preconnects) units 5, 6, and 0 and associates them with their respective operating system standard I/O files if the corresponding FORTn environment variable is not set.
You can change these preconnected files by using one of the following:
Table 7-5 lists the Compaq Fortran environment variables and the standard I/O file associations for the preconnected files.
Unit | Compaq Fortran Environment Variable |
Equivalent Tru64 UNIX Standard I/O File |
---|---|---|
5 | FORT5 | Standard input, stdin |
6 | FORT6 | Standard output, stdout |
0 | FORT0 | Standard error, stderr |
To change the characteristics of the connection to a preconnected unit, explicitly open the preconnected unit number.
To redirect input or output from the standard preconnected files at run-time, you can set the appropriate Compaq Fortran I/O environment variable (see Section 7.5.7) or use the appropriate shell redirection character in a pipe (such as > or <).
The OPEN statement connects a unit number with an external file and allows you to explicitly specify file attributes and run-time options using OPEN statement specifiers. Once you open a file, you should close it before opening it again unless it is a preconnected file.
If you open a unit number that was opened previously (without being closed), one of the following occurs:
You can use the INQUIRE statement (see Section 7.6) to obtain information about a whether or not a file is opened by your program.
Especially when creating a new file using the OPEN statement, examine the defaults (see the description of the OPEN statement in the Compaq Fortran Language Reference Manual) or explicitly specify file attributes with the appropriate OPEN statement specifiers.
Table 7-6 lists the OPEN statement functions and their specifiers.
Category, Functions, and OPEN Statement Specifiers | |
---|---|
Identify File and Unit | |
UNIT specifies the logical unit number. | |
FILE (or NAME 1) and DEFAULTFILE 1 specify the directory and/or file name of an external file. | |
STATUS or TYPE 1 indicates whether to create a new file, overwrite an existing file, open an existing file, or use a scratch file. | |
STATUS or DISPOSE 1 specifies the file existence status after CLOSE. | |
File and Record Characteristics | |
ORGANIZATION 1 indicates the file organization (sequential or relative). | |
RECORDTYPE 1 indicates which record type to use. | |
FORM indicates whether records are formatted or unformatted. | |
CARRIAGECONTROL 1 indicates the terminal control type. | |
RECL or RECORDSIZE 1 specifies the record size (see Section 7.4.4). | |
Special File Open Routine | |
USEROPEN 1 names the routine that will open the file to establish special context that changes the effect of subsequent Compaq Fortran I/O statements (see Section 7.9). | |
File Access, Processing, and Position | |
ACCESS indicates the access mode (direct or sequential). | |
SHARED 1 indicates that other users can access the same file and activates record locking. Ignored in the current version of Compaq Fortran for Tru64 UNIX and Linux Systems (see Section 7.8.2). | |
POSITION indicates whether to position the file at the beginning of file, before the end-of-file record, or leave it as is (unchanged). | |
ACTION or READONLY 1 indicates whether statements will be used to only read records, only write records, or both read and write records. | |
MAXREC 1 specifies the maximum record number for direct access. | |
ASSOCIATEVARIABLE 1 specifies the variable containing next record number for direct access. | |
Record Transfer Characteristics | |
BLANK indicates whether to ignore blanks in numeric fields. | |
DELIM specifies the delimiter character for character constants in list-directed or namelist output. | |
PAD, when reading formatted records, indicates whether padding characters should be added if the item list and format specification require more data than the record contains. | |
BLOCKSIZE 1 specifies the block physical I/O buffer size. | |
BUFFERCOUNT 1 specifies the number of physical I/O buffers. | |
CONVERT 1 specifies the format of unformatted numeric data (see Chapter 10). | |
Error Handling Capabilities | |
ERR specifies a label to branch to if an error occurs. | |
IOSTAT specifies the integer variable to receive the error (IOSTAT) number if an error occurs. | |
File Close Action | |
DISPOSE identifies the action to take when the file is closed. |
You can choose to assign files to logical units by using one of the following methods:
PRINT *,100 |
OPEN (UNIT=7,STATUS='NEW') READ (7,100) |
OPEN (UNIT=7, FILE='FILNAM.DAT', STATUS='OLD') |
The following sections discuss these methods.
7.5.4 Accessing Files: Implied and Explicit File and Pathnames
Most I/O operations involve a disk file, keyboard, or screen display. Other devices can also be used:
For information on USEROPEN routines, see Section 7.9.
You can access the terminal screen or keyboard by using preconnected files, as described in Section 7.5. Otherwise, this chapter discusses disk files.
A complete file specification consists of a file name usually preceded by a pathname that specifies a directory. The pathname can be in one of two forms:
/usr/users/gdata/testdata |
gdata/testdata |
Directory names and file names should not contain any operating system wildcard characters (such as *, ?, and the [ ] construct). You can use the tilde (~) character as the first character in a pathname to refer to a top-level directory as in the C shell.
When specifying files, keep in mind that trailing and leading blanks are removed from character expression names, but not from Hollerith (numeric array) names.
File names are case sensitive and can consist of uppercase and lowercase letters. For example, the following file names represent three different files:
myfile.for MYfile.for MYFILE.for |
You can associate a logical unit with a directory (if needed) and file
name by using an environment variable assignment (see Section 7.5.7)
or by using the OPEN statement (see Section 7.5.6). When an OPEN
statement provides a pathname that contains only a directory (no file
name) and an environment variable provides the file name, the OPEN
statement and environment variable can work together to provide the
complete directory and file name.
7.5.5 How Compaq Fortran Applies a Default Pathname and File Name
Compaq Fortran provides the following possible ways of specifying all or part of a file specification (directory and file name), such as /usr/proj/testdata :
Compaq Fortran recognizes environment variables for each logical I/O unit number in the form of FORTn, where n is the logical I/O unit number. If a file name is not specified in the OPEN statement and the corresponding FORTn environment variable is not set for that unit number, Compaq Fortran generates a file name in the form fort.n , where n is the logical unit number.
Certain Compaq Fortran environment variables are recognized and preconnected files exist for certain unit numbers, as described in Section 7.5.7.
When using scratch files, you can use the TMPDIR environment variable to specify where the scratch file gets created (see Section 7.4.2).
Performing an implied OPEN means that the FILE and DEFAULTFILE specifier values are not specified and an environment variable is used, if present.
Examples of Applying Default Pathnames and File Names
For example, for an implied OPEN of unit number 3, Compaq Fortran would check the environment variable FORT3. If the environment variable FORT3 was set, its value is used. If it is not set, the system supplies the file name fort.3 .
In Table 7-7, assume the current directory is /usr/smith and the I/O uses unit 1, as in the statement READ (1,100) .
OPEN FILE Value |
OPEN DEFAULTFILE Value | FORT1 Environment Variable Value |
Resulting Pathname |
---|---|---|---|
not specified | not specified | not specified | /usr/smith/fort.1 (1) |
not specified | not specified | test.dat | /usr/smith/test.dat (2) |
not specified | not checked | /usr/tmp/t.dat | /usr/tmp/t.dat (3) |
not specified | /tmp | not specified | /tmp/fort.1 (4) |
not specified | /tmp | testdata | /tmp/testdata (5) |
not specified | /usr | lib/testdata | /usr/lib/testdata (6) |
file.dat | /usr/group | not checked | /usr/group/file.dat (7) |
/tmp/file.dat | not checked | not checked | /tmp/file.dat (8) |
file.dat | not specified | not specified | /usr/smith/file.dat (9) |
When the resulting file pathname begins with a tilde character (~), C shell style pathname substitution is used (regardless of what shell is being used), such as a top-level directory (below the root). For additional information on tilde pathname substitution, see csh(1).
Rules for Applying Default Pathnames and File Names
Compaq Fortran determines file name and the directory path based on certain rules. It determines a file name string as follows:
Once Compaq Fortran determines the resulting file name string, it determines the directory (which optionally precedes the file name) as follows:
You can use the FILE and DEFAULTFILE specifiers of the OPEN statement to specify the complete definition of a particular file to be opened on a logical unit. (The Compaq Fortran Language Reference Manual describes the OPEN statement in greater detail.) For example:
OPEN (UNIT=4, FILE='/usr/users/smith/test.dat', STATUS='OLD') |
The file test.dat in directory /usr/users/smith is opened on logical unit 4. No defaults are applied since both the directory and file name were specified. The value of the FILE specifier can be a character constant, variable, or expression.
In the following interactive example, the user supplies the file name and the DEFAULTFILE specifier supplies the default values for the full pathname string. The file to be opened is in /usr/users/smith and is concatenated with the file name typed by the user into the variable DOC:
CHARACTER(LEN=9) DOC WRITE (6,*) 'Type file name ' READ (5,*) DOC OPEN (UNIT=2, FILE=DOC, DEFAULTFILE='/usr/users/smith',STATUS='OLD') |
A slash is appended to the end of the default file string if it does not have one.
For an example program that reads a typed file name, uses the typed
name to open a file, and handles such errors as the "file not
found" error, see Example 8-2.
7.5.7 Using Environment Variables
You can use the environment variable mechanism of the operating system and shells to associate logical units with external files. For example, setting the environment variable FORT6 to a file lets you redirect stdout to the specified file (see Table 7-5).
Compaq Fortran attempts to use certain environment variables in the absence of a file name.
When using scratch files, you can use the TMPDIR environment variable to specify where the scratch file gets created (see Section 7.4.2).
Setting and Unsetting Environment Variables
Before program execution, you can use shell commands to specify a value for an environment variable. This specified value might be a directory and/or file name of an external file you want to associate with a preconnected unit or a specific unit number.
With the C Shell, use the setenv command to set an environment variable:
% setenv FORT8 /usr/users/smith/test.dat |
To remove the association of an environment variable and an external file with the C shell, use the unsetenv command.
% unsetenv FORT8 |
With the Bourne shell ( sh ) and Korn shell ( ksh ) and bash shell (L*X ONLY), use the export command and assignment command to set the environment variable:
$ export FORT8 $ FORT8=/usr/users/smith/test.dat |
To remove the association of an environment variable and an external file with the Bourne shell or Korn shell or bash shell (L*X ONLY), use the unset command:
$ unset FORT8 |
Implied Compaq Fortran Logical Unit Numbers
The ACCEPT, PRINT, and TYPE statements, and the use of an asterisk (*) in place of a unit number in READ and WRITE statements, do not include an explicit logical unit number. Each of these Fortran 95/90 statements uses an implicit internal logical unit number and environment variable. Each environment variable is in turn associated by default with one of the Fortran 95/90 file names that are associated with standard I/O files. Table 7-8 shows these relationships.
Compaq Fortran Statement | Environment Variable When -vms Specified | Environment Variable When -vms Omitted | Standard I/O File Name |
---|---|---|---|
READ (*,f) iolist | FOR_READ | FORT5 | stdin |
READ f,iolist | FOR_READ | FORT5 | stdin |
ACCEPT f,iolist | FOR_ACCEPT | FORT5 | stdin |
WRITE (*,f) iolist | FOR_PRINT | FORT6 | stdout |
PRINT f,iolist | FOR_PRINT | FORT6 | stdout |
TYPE f,iolist | FOR_TYPE | FORT6 | stdout |
You can change the file associated with these Compaq Fortran environment variables, as you would any other environment variable, by means of the environment variable assignment command. For example, with the C shell:
% setenv FOR_READ /usr/users/smith/test.dat |
After executing the preceding command, the environment variable for the READ statement using an asterisk refers to file test.dat in directory /usr/users/smith .
The INQUIRE statement returns information about a file and has three forms:
An inquiry by unit is usually done for an opened (connected) file. An inquiry by unit causes the Compaq Fortran RTL to check whether the specified unit is connected or not. One of the following occurs:
For example, the following INQUIRE statement shows whether unit 3 has a file connected (OPENED specifier) in logical variable I_OPENED, the name (case sensitive) in character variable I_NAME, and whether the file is opened for READ, WRITE, or READWRITE access in character variable I_ACTION:
INQUIRE (3, OPENED=I_OPENED, NAME=I_NAME, ACTION=I_ACTION) |
An inquiry by name causes the Compaq Fortran RTL to scan its list of open files for a matching file name. One of the following occurs:
The following INQUIRE statement returns whether the file named log_file is a file connected in logical variable I_OPEN, whether the file exists in logical variable I_EXIST, and the unit number in integer variable I_NUMBER:
INQUIRE (FILE='log_file', OPENED=I_OPEN, EXIST=I_EXIST, NUMBER=I_NUMBER) |
Unlike inquiry by unit or inquiry by name, inquiry by output item list does not attempt to access any external file. It returns the length of a record for a list of variables that would be used for unformatted WRITE, READ, and REWRITE statements (REWRITE is a Compaq Fortran extension).
The following INQUIRE statement returns the maximum record length of the variable list in variable I_RECLENGTH. This variable is then used to specify the RECL value in the OPEN statement:
INQUIRE (IOLENGTH=I_RECLENGTH) A, B, H OPEN (FILE='test.dat', FORM='UNFORMATTED', RECL=I_RECLENGTH, UNIT=9) |
For an unformatted file, the RECL value is returned using 4-byte units, unless you specify the -assume byterecl option to request 1-byte units.
Usually, any external file opened should be closed by the same program before it completes. The CLOSE statement disconnects the unit and its external file. You must specify the unit number (UNIT specifier) to be closed.
You can also specify:
To delete a file when closing it:
If you opened an external file and did an inquire by unit, but do not like the default value for the ACCESS specifier, you can close the file and then reopen it, explicitly specifying the ACCESS desired.
There usually is no need to close preconnected units. Internal files are neither opened nor closed.
After you open a file or use a preconnected file, you can use the following statements:
These statements are described in Section 7.2 and in the Compaq Fortran Language Reference Manual.
The record I/O statement must use the appropriate record I/O form
(formatted, list-directed, namelist, or unformatted), as described in
Section 7.3.
7.8.1 Record I/O Statement Specifiers
You can use the following specifiers with the READ and WRITE record I/O statements:
When using nonadvancing I/O, use the ADVANCE, EOR, and SIZE specifiers, as described in Section 7.8.4.
When using the REWRITE statement (a Compaq Fortran extension), you can use the UNIT, FMT, ERR, and IOSTAT specifiers.
Record access refers to how records will be read from or written to a file, regardless of its organization. Record access is specified each time you open a file; it can be different each time. The type of record access permitted is determined by the combination of file organization and record type.
For instance, you can:
Sequential access transfers records sequentially to or from files or I/O devices such as terminals. You can use sequential I/O with any type of supported file organization and record type.
If you select sequential access mode for files with sequential or
relative
organization, records are written to or read from the file starting at
the beginning of the file and continuing through it, one record after
another. A particular record can be retrieved only after all of the
records preceding it have been read; new records can be written only at
the end of the file.
7.8.2.2 Direct Access
Direct access transfers records selected by record number to and from either sequential files stored on disk with a fixed-length record type or relative organization files.
If you select direct access mode, you can determine the order in which records are read or written. Each READ or WRITE statement must include the relative record number, indicating the record to be read or written.
You can directly access a sequential disk file only if it contains fixed-length records. Because direct access uses cell numbers to find records, you can enter successive READ or WRITE statements requesting records that either precede or follow previously requested records. For example, the first of the following statements reads record 24; the second reads record 10:
READ (12,REC=24) I READ (12,REC=10) J |
You can use both access modes on sequential and relative files. However, direct access to a sequential organization file can only be done if the file resides on disk and contains fixed-length records.
Table 7-9 summarizes the types of access permitted for the various combinations of file organizations and record types.
Organization | Record Type | Sequential Access | Direct Access |
---|---|---|---|
Sequential file |
Fixed
Variable Segmented Stream Stream_CR Stream_LF |
Yes
Yes Yes Yes Yes Yes |
Yes
1
No No No No No |
Relative file 1 | Fixed | Yes | Yes |
Depending on the value specified by the ACTION (or READONLY) specifier in the OPEN statement, the file will be opened by your program for reading, writing, or both reading and writing records. This simply checks that the program itself executes the type of statements intended.
For performance reasons, record-locking and shared-file checking are not supported by the current version of Compaq Fortran on Compaq Tru64 UNIX and Linux systems. When you open the file, access is always granted, regardless of whether:
Similarly, the UNLOCK statement is ignored using the current version of Compaq Fortran.
You might open a file for writing records (or reading and writing
records) and know another process might simultaneously have the file
open and be writing records. In this case, you need to coordinate
access times among those processes to handle the possibility of
simultaneous WRITE and REWRITE statements on the same record positions.
7.8.3 Specifying the Initial Record Position
When you open a disk file, you can use the OPEN statement's POSITION specifier to request one of the following initial record positions within the file:
The following I/O statements allow you to change the current record position:
Unless you use nonadvancing I/O (see Section 7.8.4), reading and
writing records usually advances the current record position by one
record. As discussed in Section 7.8.5, more than one record might be
transferred using a single record I/O statement.
7.8.4 Advancing and Nonadvancing Record I/O
After you open a file, if you omit the ADVANCE specifier (or specify ADVANCE= ' YES ' ) in READ and WRITE statements, advancing I/O (normal FORTRAN-77 I/O) will be used for record access. When using advancing I/O:
You can request nonadvancing I/O for the file by specifying the ADVANCE= ' NO ' specifier in a READ and WRITE statement. You can use nonadvancing I/O only for sequential access to external files using formatted I/O (not list-directed or namelist).
When you use nonadvancing I/O, the current record position does not change, and part of the record might be transferred, unlike advancing I/O where one entire record or records are always transferred.
You can alternate between advancing and nonadvancing I/O by specifying different values for the ADVANCE specifier ( ' YES ' and ' NO ' ) in the READ and WRITE record I/O statements.
When reading records with either advancing or nonadvancing I/O, you can use the END branch specifier to branch to a specified label when the end of the file is read.
Because nonadvancing I/O might not read an entire record, it also supports an EOR branch specifier to branch to a specified label when the end of the record is read. If you omit the EOR and the IOSTAT specifiers when using nonadvancing I/O, an error results when the end-of-record is read.
When using nonadvancing input, you can use the SIZE specifier to return the number of characters read. For example, in the following READ statement, SIZE=X (where variable X is an integer) returns the number of characters read in X and an end-of-record condition causes a branch to label 700:
150 FORMAT (F10.2, F10.2, I6) READ (UNIT=20, FMT=150, SIZE=X, ADVANCE='NO', EOR=700) A, F, I |
I/O statements transfer all data as records. The amount of data that a record can contain depends on the following circumstances:
Typically, the data transferred by an I/O statement is read from or
written to a single record. It is possible, however, for a single I/O
statement to transfer data from or to more than one record, depending
on the form of I/O used.
7.8.5.1 Input Record Transfer
When using advancing I/O, if an input statement specifies fewer data fields (less data) than the record contains, the remaining fields are ignored.
If an input statement specifies more data fields than the record contains, one of the following occurs:
If an output statement specifies fewer data fields than the record contains (less data than required to fill a record), the following occurs:
If the output statement specifies more data than the record can contain, an error occurs, as follows:
You can use the USEROPEN specifier in a Compaq Fortran OPEN statement to pass control to a routine that directly opens a file. The called routine can use system calls or library routines to open the file and establish special context that changes the effect of subsequent Compaq Fortran I/O statements.
The Compaq Fortran Run-Time Library (RTL) I/O support routines call the USEROPEN function in place of the system calls usually used when the file is first opened for I/O. The USEROPEN specifier in an OPEN statement specifies the name of a function to receive control. The called function must open the file (or pipe) and return the file descriptor of the file when it returns control to the calling Compaq Fortran program.
When opening the file, the called function usually specifies options different from those provided by a normal OPEN statement.
You can obtain the file descriptor from the Compaq Fortran Run-Time Library (RTL) for a specific unit number with the getfd routine, described in getfd(3f).
Although the called function can be written in other languages (such as Fortran), C is usually the best choice for making system calls, such as open or create .
The USEROPEN specifier for the OPEN statement has the form:
USEROPEN = function-name |
The function-name value represents the name of an external open function. In the calling Compaq Fortran program, the function must be declared in an EXTERNAL statement. For example, the following Compaq Fortran code might be used to call the USEROPEN procedure UOPEN (known to the linker as uopen_ ):
EXTERNAL UOPEN INTEGER UOPEN . . . OPEN (UNIT=10, FILE='/usr/test/data', STATUS='NEW', USEROPEN=UOPEN) |
After the OPEN statement, the uopen_ function receives control. The function opens the file, may perform other operations, and subsequently returns control (with the file descriptor) to the calling Compaq Fortran program.
If the USEROPEN function is written in C, declare it as a C function that returns a 4-byte integer (int) result to contain the file descriptor. For example:
int uopen_ ( (1) char *file_name, (2) int *open_flags, (3) int *create_mode, (4) int *lun, (5) int file_length); (6) |
The function definition and the arguments passed from the Compaq Fortran RTL are as follows:
Of the arguments, the open system call (see open(2)) requires the passed pathname, the open flags (that define the type access needed, whether the file exists, and so on), and the create mode. The logical unit number specified in the Compaq Fortran OPEN statement is passed in case the called function needs it. The hidden length of the pathname is also passed.
When creating a new file, the create system call might be used in place of open (see create(2)). You can usually use other appropriate system calls or library routines within the called function; restrictions are listed in Section 7.9.1.
In most cases, the called function modifies the open flags argument passed by the Compaq Fortran RTL or uses a new value before the open (or create ) system call. After the called function opens the file, it must return control to the main Compaq Fortran program, which can do I/O with Fortran 95/90 statements to the file.
The open system call returns the file descriptor, which must be returned as a 4-byte integer to the Compaq Fortran program (and Compaq Fortran RTL). After control (and the file descriptor) is returned from the called function, the main Compaq Fortran program can perform I/O to that logical unit with Fortran 95/90 statements and eventually close it.
If the USEROPEN function is written in Fortran, declare it as a FUNCTION with an INTEGER (KIND=4) result, perhaps with an interface block. In any case, the called function must return the file descriptor as a 4-byte integer to the calling Compaq Fortran program.
If your application requires that you use C to perform the file open
and close, as well as all record operations, call the appropriate C
procedure from the Compaq Fortran program without using the Fortran
OPEN statement. For more information on calling between Fortran and C,
see Section 11.3.
7.9.1 Restrictions of Called USEROPEN Functions
The Compaq Fortran RTL uses exactly one file descriptor per logical unit, which must be returned by the called function. Because of this, only certain Compaq Tru64 UNIX system calls or library routines can be used to open the file.
System calls and library routines that do not return a file
descriptor include
mknod
(see mknod(2)) and
fopen
(see fopen(3)). For example, the
fopen
routine returns a file pointer instead of a file descriptor.
7.9.2 Example USEROPEN Program and Function
The following Compaq Fortran code calls the USEROPEN function named UOPEN:
EXTERNAL UOPEN INTEGER UOPEN . . . OPEN (UNIT=1,FILE='ex1.dat',STATUS='NEW',USEROPEN=UOPEN, ERR=9,IOSTAT=errnum) |
If the default f90 options are used, the external name is passed using lowercase letters with an appended trailing underscore (_). In the preceding example, the external function UOPEN would be known as uopen_ to the linker and must be declared in C as uopen_. The function might be given the file name uopen_.c .
Compiling and Linking the C and Compaq Fortran Programs
Use a single f90 command to compile the called uopen_ C function uopen_.c and the Compaq Fortran calling program ex1.f . The same command also links both object files by using the appropriate libraries to create the file a.out file, as follows:
% f90 ex1.f uopen_.c |
If appropriate for large applications, you can specify object modules ( .o files) on the f90 command line. For more information on retaining object files, see Section 2.1.5.
Source Code for the C Function and Header File
Example 7-1 shows the C language function called uopen_ and its associated header file.
Example 7-1 C Function Called by USEROPEN Procedure |
---|
/* ** File: uopen.h -- header file for uopen_.c */ #ifndef UOPEN #define UOPEN 1 /* ** ** Function Prototypes ** */ int uopen_ ( char *file_name, /* access read: name of the file to open. */ int *open_flags, /* access read: READ/WRITE, see file.h or open(2)*/ int *create_mode, /* access read: set if new file (to be created).*/ int *lun, /* access read: logical unit file opened on.*/ int file_length); /* access read: number of characters in file_name*/ #endif /* End of file uopen.h */ /* ** File: uopen_.c */ /* ** This routine opens a file using data passed by Compaq Fortran RTL. ** ** INCLUDE FILES */ #include <sys/types.h> #include <sys/stat.h> #include <sys/file.h> #include "uopen.h"/* Include file for this module */ int uopen_ (file_name, open_flags, create_mode, lun, file_length) /* ** Open a file using the parameters passed by the calling Compaq ** Fortran 95/90 program. ** ** Formal Parameters: */ char *file_name; /* access read: name of the file to open. */ int *open_flags; /* access read: READ/WRITE, see file.h */ int *create_mode; /* access read: set if new file (to be created). */ int *lun; /* access read: logical unit number file opened on. */ int file_length; /* access read: number of characters in file_name. */ /* ** Function Value/Completion Code ** ** Whatever is returned by open, is immediately returned to the ** Fortran OPEN. the returned value is the following : ** value >= 0 is a valid fd. ** value < 0 is an error. ** ** Modify open flags (logical OR) to specify the file be opened for ** write access only, with records appended at the end (such as ** writing to a shared log file). */ { int result ; /* Function result value */ *open_flags = O_CREAT | O_WRONLY | O_APPEND; result = open (file_name, *open_flags, *create_mode) ; return (result) ; /* return file descriptor or error */ }/* End of routine uopen_ */ /* End of file uopen_.c */ |
Source Code for the Calling Compaq Fortran Program
Example 7-2 shows the Fortran 95/90 program that calls the uopen_ C function and then performs I/O.
Example 7-2 Compaq Fortran USEROPEN Main Calling Program |
---|
C C Program EX1 opens a file using USEROPEN and writes records to it. C It closes and re-opens the file (without USEROPEN) and reads 10 records. PROGRAM EX1 EXTERNAL UOPEN ! The USEROPEN function. INTEGER ERRNUM, CTR, I 1 FORMAT (I) ERRNUM = 0 WRITE (6,*) 'EX1. Access data using formatted I/O.' WRITE (6,*) 'EX1. Open file with USEROPEN and put some data in it.' OPEN (UNIT=1, FILE='ex1.dat', STATUS='NEW', USEROPEN=UOPEN, ERR=9, & IOSTAT=errnum) DO CTR=1,10 WRITE (1,1) CTR END DO WRITE (6,*) 'EX1. Close and re-open without USEROPEN.' CLOSE (UNIT=1) OPEN (UNIT=1, FILE='ex1.dat', STATUS='OLD', FORM='FORMATTED', ERR=99, & IOSTAT=errnum) WRITE (6,*) 'EX1. Read and display what is in file.' DO CTR=1,10 READ (1,1) i WRITE (6,*) i END DO WRITE (6,*) 'EX1. Successful if 10 records shown.' CLOSE (UNIT=1,STATUS='DELETE') STOP 9 WRITE (6,*) 'EX1. Error on USEROPEN is ', errnum STOP 99 WRITE (6,*) 'EX1. Error on 2nd open is ', errnum END PROGRAM EX1 |
For general information, see Section 7.4.3, Record Types, Record Overhead, and Maximum Record Length and Table 7-3, Compaq Fortran Record Types.
7.10.1 Fixed-Length Records
When you specify fixed-length records, all records in the file contain the same number of bytes. When you open a file that is to contain fixed-length records, you must specify the record size by using the RECL specifier. A sequentially organized file opened for direct access must contain fixed-length records, to allow the record position in the file to be computed correctly.
For relative files, the layout and overhead of fixed-length records depends on whether the program accessing the file was compiled with the -vms option or whether the -vms option was omitted:
Figure 7-1 shows the record layout of fixed-length records.
Figure 7-1 Fixed-Length Records
Variable-length records can contain any number of bytes up to a specified maximum record length, and apply only to sequential files.
Variable-length records are prefixed and suffixed by four bytes of control information containing length fields. The trailing length field allows a BACKSPACE request to skip back over records efficiently. The 4-byte integer value stored in each length field indicates the number of data bytes (excluding overhead bytes) in that particular variable-length record.
The character count field of a variable-length record is available when you read the record by issuing a READ statement with a Q format descriptor. You can then use the count field information to determine how many bytes should be in an I/O list.
The record layout of variable-length records that are less than two gigabytes appears in Figure 7-2.
Figure 7-2 Variable-Length Records Less Than 2 Gigabytes
For a record length greater than 2,147,483,639 bytes, the record is divided into subrecords. The subrecord can be of any length from 1 to 2,147,483,639, inclusive.
The sign bit of the leading length field indicates whether the record is continued or not. The sign bit of the trailing length field indicates the presence of a preceding subrecord. The position of the sign bit is determined by the endian format of the file.
A subrecord that is continued has a leading length field with a sign bit value of 1. The last subrecord that makes up a record has a leading length field with a sign bit value of 0. A subrecord that has a preceding subrecord has a trailing length field with a sign bit value of 1. The first subrecord that makes up a record has a trailing length field with a sign bit value of 0.
The record layout of variable-length records that are greater than two gigabytes appears in Figure 7-3.
Figure 7-3 Variable-Length Records Greater Than 2 Gigabytes
Files written with variable-length records by Compaq Fortran programs
usually cannot be accessed as text files. Instead, use the Stream_LF
record format for text files with records of varying length.
7.10.3 Segmented Records
A segmented record is a single logical record consisting of one or more variable-length, unformatted records in a sequentially organized disk file. Unformatted data written to sequentially organized files using sequential access is stored as segmented records by default.
Segmented records are useful when you want to write exceptionally long records but cannot or do not wish to define one long variable-length record, perhaps because virtual memory limitations can prevent program execution. By using smaller, segmented records, you reduce the chance of problems caused by virtual memory limitations on systems on which the program may execute.
For disk files, the segmented record is a single logical record that consists of one or more segments. Each segment is a physical record. A segmented (logical) record can exceed the absolute maximum record length (2.14 billion bytes), but each segment (physical record) individually cannot exceed the maximum record length.
To access an unformatted sequential file that contains segmented records, specify FORM= ' UNFORMATTED ' and RECORDTYPE= ' SEGMENTED ' when you open the file. Otherwise, the file may be processed erroneously.
As shown in Figure 7-4, the layout of segmented records consists of four bytes of control information followed by the user data.
Figure 7-4 Segmented Records
The control information consists of a 2-byte integer record size count (includes the two bytes used by the segment identifier), followed by a 2-byte integer segment identifier that identifies this segment as one of the following:
Identifier Value | Segment Identified |
---|---|
0 | One of the segments between the first and last segments. |
1 | First segment. |
2 | Last segment. |
3 | Only segment. |
If the specified record length is an odd number, the user data will be
padded with a single blank (one byte), but this extra byte is not added
to the 2-byte integer record size count.
7.10.4 Stream File Data
A Stream file is not grouped into records and contains no control information. Stream files are used with CARRIAGECONTROL= ' NONE ' and contain character or binary data that is read or written only to the extent of the variables specified on the input or output statement.
The layout of a Stream file appears in Figure 7-5.
Figure 7-5 Stream File Records
A Stream_CR or Stream_LF record is a variable-length record whose length is indicated by explicit record terminators embedded in the data, not by a count. These terminators are automatically added when you write records to a stream-type file and are removed when you read records.
Each variety uses a different 1-byte record terminator:
The layout of Stream_CR and Stream_LF records appears in Figure 7-6.
Figure 7-6 Stream_CR and Stream_LF Records
Previous | Next | Contents | Index |