Previous | Contents | Index |
This chapter describes Compaq Fortran input/output (I/O) as implemented for Compaq Fortran. It also provides information about Compaq Fortran I/O in relation to the OpenVMS Record Management Services (RMS) and Run-Time Library (RTL).
The following topics are addressed in this chapter:
Compaq Fortran assumes all unformatted data files will be in the same native little endian numeric formats used in memory. If you need to read or write unformatted numeric data (on disk) that has a different numeric format than that used in memory, see Chapter 9.
You can use Compaq Fortran I/O statements to communicate between processes on either the same computer or different computers.
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, the following READ statement uses logical unit number 2:
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. You can use the LIB$GET_LUN library routine to return a logical unit number not currently in use by your program. If you intend to use LIB$GET_LUN, avoid using logical unit numbers (UNIT) 100 to 119 (reserved for LIB$GET_LUN).
Compaq 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 command procedure can set the appropriate logical name or allow the terminal user to type a directory, 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).
ACCEPT, TYPE, and PRINT statements do not refer explicitly to a logical unit (a file or device) from which or to which data is to be transferred; they refer implicitly to a default preconnected logical unit. The ACCEPT statement is normally preconnected to the default input device, and the TYPE and PRINT statements are normally preconnected to the default output device. These defaults can be overridden with appropriate logical name assignments (see Section 6.5.1.2).
READ, WRITE, and REWRITE statements refer explicitly to a specified logical unit from which or to which data is to be transferred. However, to use a preconnected device for READ (SYS$INPUT) and WRITE (SYS$OUTPUT), specify the unit number as an asterisk (*).
Certain unit numbers are preconnected to OpenVMS standard devices. Unit number 5 is associated with SYS$INPUT and unit 6 with SYS$OUTPUT. 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 and 6 and associates them with their respective operating system standard I/O files.
On the OPEN statement and preconnected files, see Section 6.5.
6.2 Types of I/O Statements
Table 6-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 SYS$OUTPUT (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 SYS$INPUT. 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. Certain restrictions apply. |
UNLOCK | Releases a lock held on the current record when file sharing was requested when the file was opened (see Section 6.8.2). |
TYPE | Writes record output to SYS$OUTPUT (same as PRINT). |
DEFINE FILE | Specifies file characteristics for a direct access relative file and connects the unit number to the file (like an OPEN statement). Provided for compatibility with compilers older than 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.
6.3 Forms of I/O Statements
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 6.8.2, you can access records in any sequential, relative, or indexed file using sequential access. For relative files and fixed-length sequential files, you can also access records using direct access. For indexed files, you can use keyed access.
Table 6-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, and REWRITE
1
READ, WRITE, PRINT, ACCEPT 1, TYPE 1, and REWRITE 1 READ, WRITE, PRINT, ACCEPT 1, TYPE 1, and REWRITE 1 READ, WRITE, and REWRITE 1 |
External file, direct access | |
Formatted
Unformatted |
READ, WRITE, and REWRITE
1
READ, WRITE, and REWRITE 1 |
External file, keyed access | |
Formatted
Unformatted |
READ, WRITE, and REWRITE
1
READ, WRITE, and REWRITE 1 |
Internal file 2 | |
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.
6.4.1 File Organizations
File organization refers to the way records are physically arranged on a storage device.
The default file organization is always ORGANIZATION= ' SEQUENTIAL ' for an OPEN statement.
Compaq Fortran supports three kinds of file organizations: sequential, relative, and indexed sequential. The organization of a file is specified by means of the ORGANIZATION specifier in the OPEN statement.
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 and line printers, as sequential files.
File characteristics, including the file organization and record type, are stored by RMS in the disk file header and can be obtained by using the INQUIRE statement. You can also view the organization of a file using the DCL command DIRECTORY/FULL.
For more information on the INQUIRE statement, see Section 6.6 and the Compaq Fortran Language Reference Manual.
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 stored on disk with a fixed-length record type 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).
Relative files allow you to use direct access and detect when a record has been deleted.
When creating a relative file, specify the RECL value to determine the size of the fixed-length cells. Within the cells, you can store variable-length records as long as their size does not exceed the cell size.
An indexed file consists of two or more separate sections: one section contains the data records and the other sections contain indexes. When an indexed file is created, each index is associated with a specification defining a field within each record, called a key field or simply key. A record in an indexed file must contain at least one key, called the primary key, which determines the location of the records within the body of the file.
The keys of all records are collected to form one or more structured indexes, through which records are always accessed. The structure of the indexes allows a program to access records in an indexed file either randomly (keyed access) or sequentially (sequential access). With keyed access, you specify a particular key value. With sequential access, you retrieve records with increasing or decreasing key values. You can mix keyed access and sequential access.
Indexed files are supported only on disk devices. When creating an indexed file, specify the RECL value.
For more information on indexed files, see Chapter 12.
6.4.2 Internal Files and Scratch Files
Compaq Fortran also supports two other types of files that are not file organizations---namely, internal files and scratch files.
You can use an internal file to reference character data in a buffer when using sequential access. 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 such 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 variable, array element, or substring. 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 ' on an OPEN statement. By default, the files are created on the user's default disk (SYS$DISK) and are not placed in a directory or given a name that is externally visible (accessible using the DCL command DIRECTORY).
You can create scratch files on a disk other than the default disk by
using the FILE specifier in an OPEN statement.
6.4.3 I/O Record Types
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, relative, or indexed files. You can use any of the record types with sequential files.
Records are stored in one the following record types:
You can use fixed-length and variable-length record types with sequential, relative, or indexed files.
Before you choose a record type, consider whether your application will use formatted or unformatted data. If you will be using formatted data, you can use any record type except segmented. When using unformatted data, you should avoid using the stream, stream_CR, and stream_LF record types.
The segmented record type is unique to Compaq Fortran products; it is not used by other OpenVMS-supported languages. It 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 Fortran.
The stream, stream_CR, stream_LF, and segmented record types can only
be used with sequential files.
6.4.3.1 Portability Considerations of Record Types
Consider the following portability needs when choosing a record type:
Compaq Fortran indexed files are portable only to other OpenVMS systems.
However, a conversion program can read the records from an indexed file
and write them to another file, such as a sequential (or relative) file.
6.4.3.2 Fixed-Length Records
When you create a file that uses the fixed-length record type, you must specify the record size. When you specify fixed-length records, all records in the file must contain the same number of bytes. (The Compaq Fortran Language Reference Manual discusses fixed-length records.)
A sequential file opened for direct access must contain fixed-length records, to allow the record position in the file to be computed correctly.
You can obtain the record length (RECL) before opening the file with
unformatted data by using a form of the INQUIRE statement (see
Section 6.6.3).
6.4.3.3 Variable-Length Records
Variable-length records can contain any number of bytes, up to a specified maximum. These records are prefixed by a count field, indicating the number of bytes in the record. The count field comprises two bytes on a disk device and four bytes on magnetic tape. The value stored in the count field indicates the number of data bytes in the record.
Variable-length records in relative files are actually stored in fixed-length cells, the size of which must be specified by means of the RECL specifier in an OPEN statement (see the Compaq Fortran Language Reference Manual for details). This RECL value specifies the largest record that can be stored in the file.
The count field of a formatted 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.
6.4.3.4 Segmented Records
A segmented record is a single logical record consisting of one or more variable-length, unformatted records in a sequential file. Each variable-length record constitutes a segment. The length of a segmented record is arbitrary.
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. When writing unformatted data to a sequential file using sequential access, the default record type is segmented.
As shown in Figure 6-1, the layout of segmented records consists of control information followed by the user data. On disk, the control information consists of four bytes for compatibility with other Compaq Fortran platforms. However, OpenVMS RMS removes the first two length bytes when the record is read, so each record has two control bytes (flags) in memory.
Figure 6-1 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. |
When you wish to access an unformatted sequential file that contains variable-length records, you must specify FORM='UNFORMATTED' when you open the file. If the unformatted data file was not created using a Compaq Fortran product, specify RECORDTYPE='VARIABLE'. If the unformatted data file was created using the segmented record type using a Compaq Fortran product, specify RECORDTYPE='SEGMENTED'.
Otherwise, the first two bytes of each record will be mistakenly interpreted as control information, and errors will probably result.
You can obtain the record length (RECL) before opening the file with
unformatted data using a form of the INQUIRE statement (see
Section 6.6.3).
6.4.3.5 Stream Records
A stream record is a variable-length record whose length is indicated by explicit record terminators embedded in the data, not by a count.
Stream files use the 2-character sequence consisting of a carriage-return and a line-feed as the record terminator. These terminators are automatically added when you write records to a stream file and removed when you read records.
Stream records resemble the Stream_CR or Stream_LF records shown in
Figure 6-2, but use a 2-byte record terminator (carriage-return and
line-feed) instead of a 1-byte record terminator.
6.4.3.6 Stream_CR and Stream_LF 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 6-2.
Figure 6-2 Stream_CR and Stream_LF Records
Other file characteristics include:
The units used for specifying record length depend on the form of the data:
You can choose to open files by:
PRINT *,100 |
OPEN (UNIT=7,STATUS='OLD') READ (7,100) |
READ (7,100) . . . TYPE 100 |
OPEN (UNIT=7, FILE='LOGNAM', STATUS='OLD') |
OPEN (UNIT=7, FILE='FILNAM.DAT', STATUS='OLD') |
If you choose to specify a logical name with the FILE specifier in an
OPEN statement, that logical name must be associated with a file
specification and the character expression specified for the logical
name must contain no punctuation marks.
6.5.1 Preconnected Files and Fortran Logical Names
You can use OpenVMS logical names to associate logical units with file specifications. A logical name is a string up to 255 characters long that you can use as part of a file specification.
Table 6-3 lists the OpenVMS process logical names for standard I/O devices already associated with particular file specifications.
OpenVMS Logical Name | Meaning | Default |
---|---|---|
SYS$COMMAND | Default command stream | For an interactive user, the default is the terminal; for a batch job, the default is the batch job input command file. |
SYS$DISK | Default disk device | As specified by user. |
SYS$ERROR | Default error stream | For an interactive user, the default is the terminal; for a batch job, the default is the batch job log file. |
SYS$INPUT | Default input stream | For an interactive user, the default is the terminal; for a batch job, the default is the batch command file. |
SYS$OUTPUT | Default output stream | For an interactive user, the default is the terminal; for a batch job, the default is the batch log file. |
You can dynamically create a logical name and associate it with a file specification by means of the DCL commands ASSIGN or DEFINE. For example, before program execution, you can define each logical name recognized by your program with a file specification appropriate to your needs without recompiling and relinking the program. For example:
$ DEFINE LOGNAM USERD:[SMITH]TEST.DAT;2 |
The preceding command creates the logical name LOGNAM and associates it with the file specification USERD:[SMITH]TEST.DAT;2. As a result, this file specification is used whenever the logical name LOGNAM is encountered during program execution.
The following statement opens the file associated with the current definition of the logical name LOGNAM:
OPEN (UNIT=7, FILE='LOGNAM', STATUS='OLD') |
Logical names provide great flexibility because they can be associated
with either a partial or complete file specification (with either a
device or a device and a directory), or even another logical name.
6.5.1.1 Preconnected Files
ACCEPT, TYPE, and PRINT statements do not refer explicitly to a logical unit (a file or device) from which or to which data is to be transferred; they refer implicitly to a default preconnected logical unit. ACCEPT refers to the default input device SYS$INPUT. TYPE and PRINT refer to the default output device SYS$OUTPUT. These defaults can be overridden with appropriate logical name assignments (see Section 6.5.1.2).
READ, WRITE, and REWRITE usually refer to explicit unit numbers. If you do not use an OPEN statement to open logical unit 5 or 6 without setting the appropriate logical name (FORnnn), unit number 5 is associated with SYS$INPUT and unit 6 with SYS$OUTPUT.
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 and 6 and associates them with their respective operating system standard I/O files if the corresponding logical name is not set.
To redirect I/O to an external disk file instead of these preconnected files, you can either use an OPEN statement to unit 5 and 6 or set the appropriate logical name. If you set the corresponding Compaq Fortran logical name, the file specified by that Compaq Fortran logical name is used.
The order of precedence when you open a file is:
Table 6-4 shows the I/O statements and their associated Fortran logical names and OpenVMS standard I/O logical names.
Statement | Fortran Logical Name1 | Equivalent OpenVMS Logical Name1 |
---|---|---|
READ (*,f) iolist | FOR$READ | SYS$INPUT |
READ f,iolist | FOR$READ | SYS$INPUT |
ACCEPT f,iolist | FOR$ACCEPT | SYS$INPUT |
WRITE (*,f) iolist | FOR$PRINT | SYS$OUTPUT |
PRINT f,iolist | FOR$PRINT | SYS$OUTPUT |
TYPE f,iolist | FOR$TYPE | SYS$OUTPUT |
READ (5),iolist | FOR005 | SYS$INPUT |
WRITE (6),iolist | FOR006 | SYS$OUTPUT |
You can change the file specifications associated with these Fortran
logical names by using the DCL commands DEFINE or ASSIGN.
6.5.1.2 Compaq Fortran Logical Names
Compaq Fortran I/O is usually performed by associating a logical unit number with a device or file. OpenVMS logical names provide an additional level of association; a user-specified logical name can be associated with a logical unit number.
Compaq Fortran provides predefined logical names in the following form:
FORnnn |
The notation nnn represents a logical unit number, any non-negative 4-byte integer (maximum value is 2,147,483,647). For example, for logical unit 12, the predefined logical name would be FOR012; for logical unit 1024, the predefined logical name would be FOR1024.
By default, each Fortran logical name is associated with a file named FORnnn.DAT on your default disk under your default directory. For example:
WRITE (17,200) |
If you enter the preceding statement without including an explicit file specification, the data is written to a file named FOR017.DAT on your default disk under your default directory.
You can change the file specification associated with a Fortran logical unit number by using the DCL commands ASSIGN or DEFINE to change the file associated with the corresponding Fortran logical name. For example:
$ DEFINE FOR017 USERD:[SMITH]TEST.DAT;2 |
The preceding command associates the Fortran logical name FOR017 (and therefore logical unit 17) with file TEST.DAT;2 on device USERD in directory [SMITH].
You can also associate the Fortran logical names with any of the predefined system logical names, as shown in the following examples:
$ DEFINE FOR010 SYS$OUTPUT |
$ DEFINE SYS$COMMAND SYS$INPUT |
On the DCL commands you can use to assign or deassign logical names,
see Appendix C.
6.5.2 Disk Files and File Specifications
Most I/O operations involve a disk file, keyboard, or screen display. You can access the terminal screen or keyboard by using preconnected files, as described in Section 6.5. Otherwise, this chapter discusses disk files.
Compaq Fortran recognizes logical names for each logical I/O unit number in the form of FORnnn, where nnn is the logical I/O unit number, with leading zeros for fewer than three digits. If a file name is not specified in the OPEN statement and the corresponding FORnnn logical name is not set for that unit number, Compaq Fortran generates a file name in the form FORnnn.DAT, where n is the logical unit number.
Certain Compaq Fortran logical names are recognized and preconnected files exist for certain unit numbers. Performing an implied OPEN means that the FILE and DEFAULTFILE specifier values are not specified and a logical name is used, if present.
A complete OpenVMS file specification has the form:
node::device:[directory]filename.filetype;version |
For example:
BOSTON::USERD:[SMITH]TEST.DAT;2 |
You can associate a file specification with a logical unit by using a logical name assignment (see Section 6.5.1) or by using an OPEN statement (see Section 6.5.2). If you do not specify such an association or if you omit elements of the file specification, the system supplies default values, as follows:
For example, if your default device is USERD and your default directory is SMITH, and you specified the following statements:
READ (8,100) . . . WRITE (9,200) |
The default input file specification would be:
USERD:[SMITH]FOR008.DAT;n |
The default output file specification would be:
USERD:[SMITH]FOR009.DAT;m |
In these examples, n equals the highest current version number of FOR008.DAT and m is 1 greater than the highest existing version number of FOR009.DAT.
You can use the FILE and DEFAULTFILE specifiers in an OPEN statement to specify the complete definition of a particular file to be opened on a logical unit. For example:
OPEN (UNIT=4, FILE='USERD:[SMITH]TEST.DAT;2', STATUS='OLD') |
In the preceding example, the existing file TEST.DAT;2 on device USERD in directory SMITH is to be opened on logical unit 4. Neither the default file specification (FOR004.DAT) nor the Fortran logical name FOR004 is used. The value of the FILE specifier can be a character constant, variable, or expression.
Compaq Fortran provides the following possible ways of specifying all or part of a file specification (directory and file name), such as DISK2:[PROJECT.DATA]:
In the following interactive example, the file name is supplied by the user and the DEFAULTFILE specifier supplies the default values for the file specification string. The file to be opened is in device and directory DISK4:[PROJ] and is merged with the file name typed by the user into the variable DOC:
CHARACTER(LEN=40) DOC WRITE (6,*) 'Type file name ' READ (5,*) DOC OPEN (UNIT=2, FILE=DOC, DEFAULTFILE='DISK4:[PROJ]',STATUS='OLD') |
The DEFAULTFILE specification overrides your process default device and directory.
You can also specify a logical name as the value of the FILE specifier, if the logical name is associated with a file specification. If the logical name LOGNAM is defined to be the file specification USERD:[SMITH]TEST.DAT, the logical name can then be used in an OPEN statement, as follows:
OPEN (UNIT=19, FILE='LOGNAM', STATUS='OLD') |
When an I/O statement refers to logical unit 19, the system uses the file specification associated with logical name LOGNAM.
If the value specified for the FILE specifier has no associated file specification, it is regarded as a true file name rather than as a logical name. Suppose LOGNAM had not been previously associated with the file specification by using an ASSIGN or DEFINE command. The OPEN statement would indicate that a file named LOGNAM.DAT is located on the default device, in the default directory.
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 7-1.
For a detailed description of OpenVMS file specifications, see the Guide to OpenVMS File Applications.
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 6.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 6-5 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, relative, or indexed). | |
RECORDTYPE 1 indicates which record type to use. | |
FORM indicates whether records are formatted or unformatted. See Section 6.4.4 and Section 6.3. | |
CARRIAGECONTROL 1 indicates the terminal control type. | |
KEY 1 indicates (when creating an indexed file) the key number, its type, and its location. | |
NOSPANBLOCKS 1 indicates that the records should not span block boundaries. | |
RECL or RECORDSIZE 1 specifies the record size. See Section 6.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 Chapter 11). | |
File Access, Processing, and Position | |
ACCESS indicates the access mode (direct, keyed, or sequential). See Section 6.8.2. | |
ACTION or READONLY 1 indicates whether statements will be used to only read records, only write records, or read and write records. See Section 6.8.3. | |
POSITION indicates whether to position the file at the beginning of file, before the end-of-file record, or leave it as is (unchanged). See Section 6.8.4. | |
SHARED 1 indicates that other users can access the same file and activates record locking. See Section 6.8.3. | |
MAXREC 1 specifies the maximum record number for direct access. | |
ASSOCIATEVARIABLE 1 specifies the variable containing next record number for direct access. | |
File Allocation | |
INITIALSIZE 1 indicates the allocation unit (in blocks) when creating a file. | |
EXTENDSIZE 1 indicates the allocation unit (in blocks) when allocation additional file space. | |
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 9. | |
Error Handling Capabilities | |
ERR specifies a label to branch to if an error occurs. See Chapter 7. | |
IOSTAT specifies the integer variable to receive the error (IOSTAT) number if an error occurs. See Chapter 7. | |
File Close Action | |
DISPOSE 1 identifies the action to take when the file is closed. |
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 integer 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 qualifier 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 6.2 and 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 6.3.
6.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 6.8.5.
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. Access mode is the method a program uses to retrieve and store records in a file. The access mode is specified as part of each I/O statement.
Compaq Fortran supports three record access modes:
Your choice of record access mode is affected by the organization of the file to be accessed. For example, the keyed access mode can be used only with indexed organization files.
Table 6-6 shows all of the valid combinations of access mode and file organization.
File Organization | Record Access Mode | ||
---|---|---|---|
Sequential | Direct | Keyed | |
Sequential | Yes | Yes 1 | No |
Relative | Yes | Yes | No |
Indexed | Yes | No | Yes |
If you select the sequential access mode for sequential or relative files, records are written to or read from the file starting at the beginning and continuing through the file, one record after another. For indexed files, sequential access can be used to read or write all records according to the direction of the key and the key values. Sequential access to indexed files can also be used with keyed access to read or write a group of records at a specified point in the file.
When you use sequential access for sequential and relative files, a particular record can be retrieved only after all of the records preceding it have been read.
Writing records by means of sequential access also varies according to the file organization:
If you select direct access mode, you 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 access relative files directly. You can also access a sequential disk file directly if it contains fixed-length records. Because direct access uses cell numbers to find records, you can issue successive READ or WRITE statements requesting records that either precede or follow previously requested records. The following statements read record 24, then read record 10.
READ (12,REC=24) I READ (12,REC=10) J |
If you select keyed access mode, you determine the order in which records are read or written by means of character values or integer values called keys. Each READ statement contains the key that locates the record. The key value in the I/O statement is compared with index entries until the record is located.
When you insert a new record, the values contained in the key fields of the record determine the record's placement in the file; you do not have to indicate a key.
You can use keyed access only for indexed files.
Your program can mix keyed access and sequential access I/O statements on the same file. You can use keyed I/O statements to position the file to a particular record, then use sequential I/O statements to access records with either increasing or decreasing key values (depending on the key chosen).
On using indexed files, see Chapter 12.
6.8.3 Shared File Use
With the RMS file-sharing capability, you can allow file access by more
than one program at a time or by the same program on more than one
logical unit.
There are two kinds of file sharing:
All three file organizations---relative, indexed, and sequential---permit read and write access to shared files.
The extent to which file sharing can take place is determined by two factors: the type of device on which the file resides and the explicit information supplied by the user. These factors have the following effects:
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, unless the OPEN statement specifies the SHARED specifier.
To allow other users to access the same file once you have opened it, specify the OPEN statement SHARED specifier when you open the file. If you specify the SHARED specifier when opening a file that is already opened by another process, your program will be allowed to access the file.
If you omit the SHARED specifier when opening a file that is already opened by another process, your program will be denied access to the file. If you omit the SHARED specifier and are the first to open that files, file access might be denied to other users later requesting access to the file.
For performance reasons, when writing records to the file, avoid specifying the SHARED qualifier when you are certain that no other processes will access that file. Similarly, unless you will be writing records when specifying the SHARED qualifier, specify ACTION= ' READ ' .
When two or more programs are write sharing a file, each program should use one of the error-processing mechanisms described in Chapter 14.
Use of one of these controls, the RMS record-locking facility, prevents program failure due to a record-locking error.
The RMS record-locking facility, along with the logic of the program, prevents two processes from accessing the same record at the same time. Record locking ensures that a program can add, delete, or update a record without having to check whether the same record is simultaneously being accessed by another process.
When a program opens a relative, sequential, or indexed file specifying SHARED, RMS locks each record as it is accessed. When a record is locked, any program attempting to access it fails with a record-locked error. A subsequent I/O operation on the logical unit unlocks the previously accessed record, so no more than one record on a logical unit is ever locked.
In the case of a WRITE to a sequential or relative organization file opened for shared access, Compaq Fortran uses an RMS option that causes the record to be updated if it already exists in the file. This option has the side-effect of momentarily releasing the record lock, if any, and then relocking the target record. There is a small possibility that if another program is trying to access the same record at the same time, it may succeed in locking the record while it is unlocked by the first program, resulting in a record-locked error for the WRITE statement.
Locked records can be explicitly unlocked by means of Compaq Fortran's UNLOCK statement. The use of this statement minimizes the amount of time that a record is locked against access by other programs. The UNLOCK statement should be used in programs that retrieve records from a shared file but do not attempt to update them.
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 6.8.5), reading and
writing records usually advances the current record position by one
record. As discussed in Section 6.8.6, more than one record might be
transferred using a single record I/O statement.
6.8.5 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.
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:
When a Compaq Fortran output statement is executed, the record data may not be written immediately to the file or device.
To enhance performance, Compaq Fortran uses the OpenVMS RMS "write-behind" and "multibuffering" features, which group records together in a memory buffer and delays the actual device write operation until the buffers are full or the file is closed. In most cases, this is desirable (for instance, to minimize disk I/O).
For those applications that depend on data being written to the physical device immediately, "write-behind" and "multibuffering" can result in incomplete data in the case of a power loss or other severe problem that prevents the data being written.
For applications that require guaranteed file consistency for disaster recovery or transactional integrity, the RMS Journaling product is recommended. RMS Journaling provides three types of journaling:
Both After-Image and Before-Image journaling can be used without modifying the application.
Other applications that do not need the degree of safety provided by RMS journaling can use RMS features to cause data to be written to the file or device more frequently. The simplest method is to use the SYS$FLUSH system service to cause RMS to perform all pending writes immediately to disk. This also has the effect of updating the file's end-of-file pointer so that all of the data written up to that point becomes accessible. An application might choose to call SYS$FLUSH at an interval of every hundred records, for example. The more often SYS$FLUSH is called, the more often the file is updated, but the more performance is affected.
When calling SYS$FLUSH, the RMS Record Access Block (RAB) for the file must be passed as an argument. For files opened by Compaq Fortran (or Compaq Fortran 77), the FOR$RAB intrinsic function may be used to obtain the RAB. For example:
INTEGER (KIND=4) :: FOR$RAB, IUNIT . . . IREC_COUNT = 0 DO WHILE (....) . . . WRITE (IUNIT) DATA IREC_COUNT = IREC_COUNT + 1 IF (IREC_COUNT .EQ. 100) THEN CALL SYS$FLUSH(%VAL(FOR$RAB(IUNIT))) IREC_COUNT = 0 END IF END DO |
Previous | Next | Contents | Index |