Disk Files [ HP FORTRAN 77/iX Programmer's Guide ] MPE/iX 5.0 Documentation
HP FORTRAN 77/iX Programmer's Guide
Disk Files
The source or destination of an HP FORTRAN 77 I/O operation is specified
by a unit number. The preconnected units 5 and 6 were used in Chapter 2
for I/O with the standard input and output devices. To access data
on a disk file, you must first connect the file to a unit number with the
OPEN statement. For example, the statement:
OPEN(9, FILE='payroll')
connects unit number 9 with the disk file payroll. The OPEN statement
sets the file pointer to point to the first record in the file. The file
payroll can now be read or written with I/O statements specifying unit 9,
as follows:
WRITE(9, '(3I5)') i, j, k
or:
READ(9, '(3I5)') i, j, k
READ or WRITE statements access the current record in the file; the
current record is pointed to by the file pointer. After the I/O
operation, the file pointer automatically moves to the next record in the
file, making that record the new current record.
Normally an I/O statement reads or writes one record of a file. In fact,
a record can be thought of as the data read or written by a single I/O
statement. Later, however, we will see that it is possible to access
more than one record in a file with a single READ or WRITE statement.
When a program has finished the file I/O activity, the unit number should
be "disconnected" from the file with the CLOSE statement. The statement:
CLOSE(9)
breaks the connection between unit 9 and the connected file. The CLOSE
statement has the effect of flushing buffers used for file I/O and
releasing the unit number for connection to another file if necessary.
When a program terminates, an automatic CLOSE is performed on each
connected unit in the program. However, it is good practice to include a
CLOSE statement when file I/O is complete.
Default File Properties
The statements shown so far illustrate the simplest file handling
commands possible. The file payroll created is the default file type for
HP FORTRAN 77; that is, the file is a sequential access, formatted file
with unknown status. These three major properties of HP FORTRAN 77 files
are described below.
ACCESS='SEQUENTIAL'.
If ACCESS is not specified in the OPEN statement, the file will be a
sequential access file. An important characteristic of sequential access
files is that each record in the file can be a different number of bytes
in length. Consequently, records in a sequential file must be read or
written in sequential order. This is easy to do because the file pointer
is set to the first record when the file is opened and advances
automatically with each I/O statement. Later in this chapter, you will
see how to open a direct access file.
FORM='FORMATTED'.
If FORM is not specified in the OPEN statement of a sequential access
file, the file will be a formatted file. A formatted file has data in
the form of ASCII characters. I/O statements that access formatted files
must use format specifications or list-directed I/O. The formatter
converts the data between its internal form (in computer memory) to its
ASCII representation (in the file). Later in this chapter, you will see
how to open an unformatted file.
STATUS='UNKNOWN'.
If STATUS is not specified in the OPEN statement, the file will have an
unknown status. The status of a file refers to whether the file exists
when the OPEN statement executes. A file with unknown status will be
created if it does not already exist before being connected to the unit
number in the OPEN statement. Later in this chapter, you will see how to
open a file with new, old, or scratch status.
Reporting File Handling Errors
In addition to connecting a unit number to a file, the OPEN statement
also flags certain file errors by using the STATUS specifier, transfers
control when an error occurs by using the ERR specifier, and returns the
error message number by using the IOSTAT specifier.
The STATUS Specifier.
The STATUS specifier in the OPEN statement assigns a status to the file.
The four types of status are described in Table 3-1 .
Table 3-1. Status Types
------------------------------------------------------------------------------
| | |
| Status Type | Description |
| | |
------------------------------------------------------------------------------
| | |
| 'NEW' | The file will be created by the OPEN statement. If the |
| | file exists, an error occurs. This status is useful to |
| | protect against writing over an existing file. |
| | |
------------------------------------------------------------------------------
| | |
| 'OLD' | The file is expected to already exist. If the file does |
| | not exist, an error occurs. This status is useful for |
| | programs that use existing data files. |
| | |
------------------------------------------------------------------------------
| | |
| 'UNKNOWN' | If the file does not exist, the file is created; otherwise, |
| | the existing file is used. This is the default file |
| | status. |
| | |
------------------------------------------------------------------------------
| | |
| 'SCRATCH' | A file is created, named by FORTRAN, and deleted when the |
| | file is closed or when the program ends. Scratch files do |
| | not use the FILE='filename' specifier. This status is |
| | useful for programs that need a temporary file. |
| | |
------------------------------------------------------------------------------
For example, the statement:
OPEN(2, FILE='myfile', STATUS='NEW')
opens the file myfile with new status.
The STATUS specifier in the CLOSE statement assigns a closing status to
the file. The two types of status are described in Table 3-2 .
Table 3-2. The STATUS Specifier
-------------------------------------------------------------------------
| | |
| Status Type | Description |
| | |
-------------------------------------------------------------------------
| | |
| 'KEEP' | The file will be saved on the disk. This is the |
| | default file status. |
| | |
-------------------------------------------------------------------------
| | |
| 'DELETE' | The file will be purged from the disk. |
| | |
-------------------------------------------------------------------------
For example, the statement:
CLOSE(2, FILE='myfile', STATUS='KEEP')
closes the file myfile with keep status, so the file will be saved on the
disk.
A scratch file is always deleted by the system at the end of the session.
If you specify the CLOSE statement with STATUS='KEEP', an error occurs.
The ERR Specifier.
The ERR specifier in the OPEN statement assigns a statement label for the
program to jump to when an error occurs. For example, the statement:
OPEN(9, FILE='datafile', STATUS='NEW', ERR=180)
connects the logical unit 9 to the file datafile. If an error occurs in
the opening of the file, control transfers to the statement labeled 180.
The IOSTAT Specifier.
The IOSTAT specifier in the OPEN statement names the integer variable
where the system returns the error message number. The values returned
in this integer variable are summarized in Table 3-3 .
Table 3-3. The IOSTAT Specifier
---------------------------------------------------------------------
| | |
| Value of | Meaning |
| IOSTAT | |
| Integer | |
| Variable | |
| | |
---------------------------------------------------------------------
| | |
| Zero | No error occurred. |
| | |
---------------------------------------------------------------------
| | |
| Greater than | An error occurred; an error message number is |
| zero | returned. |
| | |
---------------------------------------------------------------------
The error message number refers to runtime errors. Refer to the HP
FORTRAN 77/iX Reference for a description of the error message. The
statement:
OPEN(4, FILE='xyzfile', ERR=99, IOSTAT=ios)
connects the logical unit number 4 to the file xyzfile. If an error
occurs in the opening of the file, the error number is placed in the
variable ios and control transfers to the statement labeled 99.
The CLOSE statement also reports file handling errors. For example, the
statement:
CLOSE(16, IOSTAT=ios, ERR=99, STATUS='DELETE')
disconnects the file that was connected to unit number 16 and specifies
that the file should be deleted. If an error occurs, control transfers
to the statement labeled 99 and the error number is stored in the
variable ios.
Creating a New File Using STATUS='NEW'
The OPEN statement with STATUS='NEW' creates a new file. A file can be
created by one program and used by another.
The program below creates a file and uses the OPEN statement specifiers
STATUS, ERR, and IOSTAT to leave the existing file unchanged with
repeated runs of the program.
PROGRAM open_specifiers1
INTEGER*4 account_num, number, quantity
REAL*4 price
C Create file "pfile".
C If an error occurs, ios will contain the runtime error number.
C Because STATUS='NEW' is specified, an error will occur if
C "pfile" already exists.
OPEN(9, FILE='pfile', STATUS='NEW', ERR=999, IOSTAT=ios)
C Prompt for data and read data from the standard I/O device:
WRITE(6, '(1X, "Enter number of products: ",NN)')
READ(5, *)number
C Write to the file "pfile":
WRITE(9, '(1X, I10)') number
DO i = 1, number
WRITE(6, '(1X, "Enter quantity and price: ",NN)')
READ(5,*) quantity, price
WRITE(9, '(1X, I10, F9.2)') quantity, price
END DO
C Close the file "pfile"; terminate connection to unit 9:
CLOSE(9)
STOP 'Normal termination'
999 CALL report_error(ios, 'OPEN', 'pfile')
STOP "Error termination"
END
SUBROUTINE report_error(ios, stmt_name, file_name)
INTEGER*4 ios, eof, found, not_found
CHARACTER stmt_name*(*), file_name*(*)
PARAMETER (eof = -1, found = 918, not_found = 908)
IF (ios .EQ. found) THEN
WRITE(6,*) stmt_name, ' error: the file ',
* file_name, ' already exists.'
ELSE IF (ios .EQ. not_found) THEN
WRITE(6,*) stmt_name, ' error: the file ',
* file_name, ' was not found.'
ELSE IF (ios .LE. eof) THEN
WRITE(6,*) stmt_name, ' End of file ', file_name
ELSE
WRITE(6,*) stmt_name, ' error', ios, ' on file ', file_name
END IF
END
In this program, unit 9 is connected to the file pfile. You are prompted
to enter data for the variables number, quantity, and price. The
variable number represents the number of transactions in the pfile and
controls the number of iterations through the DO loop. The WRITE
statement to unit 9 writes the data to the file pfile with the format
(I10) for number and the format (I10, F9.2) for quantity and price.
The error handling subroutine report_error prints a message depending on
the error number assigned to ios.
In the program, the error handling subroutine uses these three variables:
---------------------------------------------------------
| | |
| Variable | Purpose |
| | |
---------------------------------------------------------
| | |
| ios | Contains the I/O error number. |
| | |
---------------------------------------------------------
| | |
| stmt_name | Contains the statement that caused the |
| | error. |
| | |
---------------------------------------------------------
| | |
| file_name | Contains the file name that caused the |
| | error. |
| | |
---------------------------------------------------------
The error subroutine in this program includes checks for some specific
errors. The error "File not found" (reported for STATUS='OLD' files) and
"File already exists" (reported for STATUS='NEW' files) generate positive
return values for ios. After the error routine, the STOP statement halts
the program and prints the message "Error termination".
A sample session of the program follows:
Enter number of products: 5
Enter quantity and price: 3, 5.16
Enter quantity and price: 2, 9.25
Enter quantity and price: 6, 1.72
Enter quantity and price: 1, 15.91
Enter quantity and price: 14, 2.75
STOP Normal Termination
After the program executes, the contents of the file pfile is:
5
3 5.16
2 9.25
6 1.72
1 15.91
14 2.75
If the file pfile already existed, an error occurs.
Reading From an Existing File Using STATUS='OLD'
To read data from an existing file, you must first open the file with the
OPEN statement. For example, the following program opens and reads the
existing file pfile that was created in the previous example. By
specifying STATUS='OLD', the file pfile must exist or else the program
will terminate.
PROGRAM open_specifiers2
INTEGER*4 number, quantity
REAL*4 price
CHARACTER stmt_name*8
C Open file "pfile"; if it does not exist, go to statement 999:
stmt_name = 'OPEN'
OPEN(9, FILE='pfile', STATUS='OLD', ERR=999, IOSTAT=ios)
C Read the file to get the number of records;
C if an error occurs, go to statement 999:
stmt_name = 'READ 1'
READ(9, '(I10)', ERR=999, IOSTAT=ios) number
C Read the file to get the data;
C if an error occurs, go to statement 999:
stmt_name = 'READ 2'
DO i = 1, number
READ(9, '(I10, F9.2)', ERR=999, IOSTAT=ios)
* quantity, price
WRITE(6, '(1X, I5, I10, F9.2)') i, quantity, price
END DO
CLOSE(9)
STOP 'Normal termination'
999 CALL report_error(ios, stmt_name, 'pfile')
STOP 'Error termination'
END
SUBROUTINE report_error(ios, stmt_name, file_name)
INTEGER*4 ios, eof, found, not_found
CHARACTER stmt_name*(*), file_name*(*)
PARAMETER (eof = -1, found = 918, not_found = 908)
IF (ios .EQ. found) THEN
WRITE(6,*) stmt_name, ' error: the file ',
* file_name, ' already exists.'
ELSE IF (ios .EQ. not_found) THEN
WRITE(6,*) stmt_name, ' error: the file ',
* file_name, ' was not found.'
ELSE IF (ios .LE. eof) THEN
WRITE(6,*) stmt_name, ' End of file ', file_name
ELSE
WRITE(6,*) stmt_name, ' error', ios, ' on file', file_name
END IF
END
This program reads the quantity and price from the file and prints each
line. The variable number controls the loop that reads the records.
Again, the CLOSE statement disconnects the unit from the file name.
One line of data is read or written by one READ or WRITE statement. The
format descriptors specified in the READ or WRITE statement define the
data of each line in the file. Therefore, each line must be read with
the same format descriptors used to write the file.
When this program executes, the following is output:
1 3 5.16
2 2 9.25
3 6 1.72
4 1 15.91
5 14 2.75
STOP Normal termination
If the file pfile did not exist, an error occurs.
Appending to a File
To write data to an existing file, you must first open the file with the
OPEN statement. For example, the following program opens and writes to
the existing file prices, whose contents are as follows:
3 5.16
2 9.25
6 1.72
1 15.91
14 2.75
The program first finds the end of the file, and then accepts the new
data.
PROGRAM write_exist
LOGICAL forever
PARAMETER (forever = .TRUE.)
INTEGER*4 number, quantity, count
REAL*4 price
C Open the file "prices" and connect it to unit 8:
OPEN(8, FILE = 'prices', STATUS='OLD')
C Position the file pointer to the end of the file:
DO WHILE (forever)
READ(8, '(X)', END=100)
END DO
C Backspace to write over the end-of-file record
100 BACKSPACE 8
C Get new data and write the data to the file "prices":
WRITE(6,*) 'How many records do you want to add?'
READ(5,*) number
DO i = 1, number
WRITE(6,*) 'Enter quantity and price: '
READ(5,*) quantity, price
WRITE(8, '(1X, I10, F9.2)') quantity, price
END DO
C Close the file; terminate connection to unit 8:
CLOSE(8)
END
A sample run is shown below:
How many records do you want to add? 2
Enter quantity and price: 1, 1.50
Enter quantity and price: 5, 2.25
After the program executes, the contents of prices look like this:
3 5.16
2 9.25
6 1.72
1 15.91
14 2.75
1 1.50
5 2.25
The new data is appended to the end of the existing file.
File Access
The examples so far have been sequential access files; unless otherwise
specified in the OPEN statement, files are opened for sequential access.
But, FORTRAN files can be accessed (read or written) in three ways:
sequential, direct, or indexed sequential.
Sequential Access Files.
Sequential access files are read and written in sequence; that is, files
are accessed in the order in which they were written. In a sequential
access file, the following is true:
* The file pointer points to the current record.
* The READ or WRITE statement operates on the current record.
* After the READ or WRITE, the file pointer advances to the next
record.
The end of a sequential file is marked by an end-of-file (EOF) record. A
diagram of how a sequential access file is structured is shown in Figure
3-1 .
Figure 3-1. Sequential Access Files
Note that each record in a sequential access file can be a different
size.
The default specifiers in the OPEN statement for sequential access files
are summarized below:
-------------------------------------------
| | |
| Specifier | Default |
| | |
-------------------------------------------
| | |
| STATUS | 'UNKNOWN' |
| | |
-------------------------------------------
| | |
| ACCESS | 'SEQUENTIAL' |
| | |
-------------------------------------------
| | |
| FORM | 'FORMATTED' |
| | |
-------------------------------------------
| | |
| BLANK | 'NULL' |
| | |
-------------------------------------------
The BLANK specifier describes how blanks within numbers are treated on
input from formatted files. If BLANK='NULL', blanks are ignored; if
BLANK='ZERO', blanks are treated as zeros.
For example, the statement: OPEN(1, FILE='infile', STATUS='OLD',
BLANK='ZERO') connects a file named infile to logical unit number one.
The file infile exists as a sequential file for formatted I/O. All blanks
will be treated as zeros on input.
Direct Access Files.
Direct access files are read and written according to the record number;
the record number can then be used in random order. Each record in the
file has a record number that is specified by the REC specifier on a READ
or WRITE statement. Each record in a direct file must be the same size,
as specified in the OPEN statement. A diagram of how a direct access
file is structured is shown in Figure 3-2 .
Figure 3-2. Direct Access Files
Note that each record is the same size and that there is no end-of-file
(EOF) record in a direct access file.
Once established, the record number of a specific record cannot be
changed or deleted, although the record can be rewritten. The records
can be read or written in any order. For example, record number 3 can be
written before writing record number 1.
The records of a direct access file cannot be read or written using
list-directed formatting. Because a direct access file does not have an
end-of-file record, the END specifier in the direct access READ or WRITE
statement is not allowed.
The default specifiers in the OPEN statement for direct access files are
summarized below:
-------------------------------------------
| | |
| Specifier | Default |
| | |
-------------------------------------------
| | |
| STATUS | 'UNKNOWN' |
| | |
-------------------------------------------
| | |
| ACCESS | 'DIRECT' |
| | |
-------------------------------------------
| | |
| FORM | 'UNFORMATTED' |
| | |
-------------------------------------------
| | |
| BLANK | 'NULL' |
| | |
-------------------------------------------
If FORM='FORMATTED' is specified, BLANK defaults to 'NULL'.
The file format of a direct access file can be formatted or unformatted,
as described below:
---------------------------------------------------------------------
| | |
| Type of Format | Description |
| | |
---------------------------------------------------------------------
| | |
| FORMATTED | Records are blank-filled to the specified |
| | record length. |
| | |
---------------------------------------------------------------------
| | |
| UNFORMATTED | Records are null-filled to the specified |
| | record length. |
| | |
---------------------------------------------------------------------
To create a direct access file, specify an OPEN statement with the
ACCESS='DIRECT' specifier and the RECL (record length) specifier. For
example, the statement:
OPEN(2, FILE='dfile', ACCESS='DIRECT', RECL=120)
opens the file dfile for direct access. The file is associated with unit
two and has a record length of 120 bytes.
A temporary scratch file can be a direct access file. The statement:
OPEN(4, STATUS='SCRATCH', ACCESS='DIRECT', RECL=120)
connects a direct access scratch file to the FORTRAN unit four.
The program below shows how to create and write data to a direct access
file.
PROGRAM direct_access
INTEGER quantity
C Open the file "dfile" for direct access
C (the record length is 120 bytes and the default type is unformatted):
OPEN(2, FILE='dfile', ACCESS='DIRECT', RECL=120)
C Prompt for number of transactions:
WRITE(6, '(A,NN)') "Enter number of transactions:"
READ(5,*) number
C Enter data and write the data to the direct access file using
C the id number as the record number:
DO i = 1, number
WRITE(6, '(A,NN)') "Enter id number: "
READ(5,*) id
WRITE(6, '(A,NN)') "Enter quantity and price: "
READ(5,*) quantity, price
WRITE(2, REC=id) quantity, price
END DO
CLOSE(2)
END
A sample run of the program is shown below:
Enter number of transactions: 5
Enter id number: 4
Enter quantity and price: 14 16.00
Enter id number: 1
Enter quantity and price: 9 9.25
Enter id number: 6
Enter quantity and price: 1 142.90
Enter id number: 2
Enter quantity and price: 60 1.50
Enter id number: 5
Enter quantity and price: 3 74.70
When the program executes, the records 4, 1, 6, 2, and 5 are written to
the file dfile.
The program below reads and prints the contents of the first five records
in reverse order from the file dfile.
PROGRAM direct_read
INTEGER quantity
C Open the file "dfile"
OPEN(2, FILE='dfile', ACCESS='DIRECT', RECL=120)
C Read and print the first five records:
DO i = 5, 1, -1
READ(2, REC=i) quantity, price
WRITE(6, '(1X, I5, I5, F9.2)') i, quantity, price
END DO
END
The program produces the following output:
5 3 74.70
4 14 16.00
3 0 0.00
2 60 1.50
1 9 9.25
Note that record 3 is filled with zeros because that record is empty.
The sequential operations READ, WRITE, BACKSPACE, ENDFILE, and REWIND can
be used on direct access files.
Indexed Sequential Access Files.
Indexed sequential files (ISAM) are read and written randomly by a key or
sequentially without a key. The key is part of the record. Files are of
fixed length. Each record in the file has a primary key and one or more
secondary or optional keys. These keys are part of the record that is
being written into the file. Each record in an ISAM file must be the
same size as specified in the OPEN statement by RECL. The ACCESS
specifier in an OPEN statement should be specified as 'KEYED' for ISAM.
An ISAM file has two physical files; a data file containing user records
and an index file holding indexes to the records in the data file.
A diagram of how an indexed sequential file is structured is shown in
Figure 3-3 .
Figure 3-3. Indexed Sequential Access Files
The system will create two files one with the name given in the OPEN
statement and the other with a K appended to the file name. If the
original file name in the OPEN statement is already eight characters
long, the system will replace the last character of the file name with a
K. For example, a file named DATAFILE would have K appended to it as
follows: DATAFILK.
The following table shows how a file is specified variable or fixed
length in an OPEN statement.
-------------------------------------------------------------------------------------------------
| | | | |
| ACCESS | RECL | RECORDTYPE | File Type. |
| | | | |
-------------------------------------------------------------------------------------------------
| | | | |
| SEQUENTIAL | Absent | | Variable file. |
| | | | |
-------------------------------------------------------------------------------------------------
| | | | |
| SEQUENTIAL | Present | | Variable file |
| | | | (RECL= maximum record length) |
| | | | |
-------------------------------------------------------------------------------------------------
| | | | |
| DIRECT | Absent | | Error. |
| | | | |
-------------------------------------------------------------------------------------------------
| | | | |
| DIRECT | Present | | Fixed record length file. |
| | | | |
-------------------------------------------------------------------------------------------------
| | | | |
| KEYED | Present | Variable | Error. |
| | | | |
-------------------------------------------------------------------------------------------------
| | | | |
| KEYED | Present | Fixed | Fixed record length ISAM file. |
| | | | |
-------------------------------------------------------------------------------------------------
| | | | |
| KEYED | Absent | Fixed | Error. |
| | | | |
-------------------------------------------------------------------------------------------------
For example, the statement:
OPEN (10,FILE='file1',KEY=(1:4:integer,10:15:character),ACCESS='keyed')
connects a file named file1 to logical unit 10.
The program below shows how to create and write data to an indexed
sequential file.
PROGRAM isam_write
STRUCTURE /cust/
INTEGER*4 phone_num ! primary key
CHARACTER*15 last_name ! first alternate key
CHARACTER*15 first_name
CHARACTER*1 middle_init
CHARACTER*20 street
CHARACTER*15 city
CHARACTER*2 state
INTEGER*4 zip
CHARACTER*6 %fill
END STRUCTURE
RECORD /cust/ customer_rec
CHARACTER*1 temp
C Open a file "test" for indexed (keyed) access with record length
C of 80 bytes and with phone number as the primary key, and the
C last name of the customer as the secondary key.
OPEN (10,FILE='test',ACCESS='keyed',RECL=80,FORM='unformatted',
1 RECORDTYPE='fixed',KEY=(1:4:INTEGER,5:19:CHARACTER))
8 WRITE (6,'(A,NN)') "continue to add(Y/N)? "
READ (5,'(A1)') temp
IF (temp .eq. 'N') GOTO 100
WRITE (6,'(A,NN)') "phone number: "
READ (5,*) customer_rec.phone
WRITE (6,'(A,NN)') "last_name: "
READ (5,10) customer_rec.last_name
WRITE (6,'(A,NN)') "first name: "
READ (5,10) customer_rec.first_name
WRITE (6,'(A,NN)') "middle init: "
READ (5,11) customer_rec.middle_init
WRITE (6,'(A,NN)') "street: "
READ (5,12) customer_rec.street
WRITE (6,'(A,NN)') "city: "
READ (5,10) customer_rec.city
WRITE (6,'(A,NN)') "state: "
READ (5,13) customer_rec.state
WRITE (6,'(A,NN)') "zip: "
READ (5,*) customer_rec.zip
WRITE (10,err=200) customer_rec
GOTO 8
10 FORMAT(A15)
11 FORMAT(A1)
12 FORMAT(A20)
13 FORMAT(A2)
100 STOP
200 PRINT *,' error in writing'
END
The program below shows how to read an ISAM file with an alternate key
and to read it sequentially.
PROGRAM isam_read
STRUCTURE /cust/
INTEGER*4 phone_num ! primary key
CHARACTER*15 last_name ! first alternate key
CHARACTER*15 first_name
CHARACTER*1 middle_init
CHARACTER*20 street
CHARACTER*15 city
CHARACTER*2 state
INTEGER*4 zip
CHARACTER*6 %fill
END STRUCTURE
CHARACTER*15 temp_name
LOGICAL done
C Open the isam file created in the previous example.
C key, recl, and recordtype are optional for an existing file
OPEN (10,FILE='test',FORM='unformatted',STATUS='old',RECL=80,
1 RECORDTYPE='fixed',KEY=(1:4:INTEGER,5:19:CHARACTER))
C Read a record with an alternate key( last name ) and list all the
C names with that name as the last name
WRITE(6,'(A,NN)') " enter the last name: "
READ (5,10) temp_name
10 FORMAT (A15)
READ (10,KEYEQ=temp_name,KEYID=1,ERR=101) customer_rec
WRITE (6,11) customer_rec.phone_num, customer_rec.last_name,
1 customer_rec.first_name
11 FORMAT (I7,X4,A,X2,A)
C Read sequentially and list phone number and the name until
C last name changes.
done = .false.
DO WHILE (not done)
READ (10,KEYEQ=temp_name,KEYID=1,ERR=101) customer_rec
IF (customer_rec.last_name = temp_name) THEN
WRITE (6,11) customer_rec.phone_num, customer_rec.last_name,
1 customer_rec.first_name
ELSE
done = .true.
ENDIF
ENDDO
STOP
101 PRINT *,'error in reading'
END
Unformatted I/O
Unformatted I/O statements do not use format descriptors and do not
convert the data on input or output. The data is transferred in internal
(binary) representation to the external device. Unformatted I/O cannot
be used for internal or formatted files. Note that terminals are opened
as formatted files.
Unformatted Input.
The unformatted READ statement transfers one line from the specified unit
to the storage locations of the variables listed in the READ statement
list.
For example, the statement:
READ (5) i, flag, ready
places values directly into i, flag, and ready without any data type
conversions from character to internal (binary) form.
The data type of each input value should agree with the type of the
corresponding list item.
The following program shows the unformatted input statements.
PROGRAM unformatted_input
INTEGER i(1000)
OPEN(9, FILE = 'bdata', FORM = 'UNFORMATTED')
C Unformatted input statements from unit 9.
C (The array i is read in internal binary format from unit 9.)
READ(9) i
CLOSE(9)
END
Unformatted Output.
The unformatted WRITE statement writes to the specified output unit
without any format conversion.
For example, the statement:
WRITE (6) i, flag, ready
writes the values of i, flag, and ready without any format conversion.
If a list is omitted in the WRITE statement, a null line is written.
Using Formatted and Unformatted Files
FORTRAN files can be either formatted or unformatted. If not specified
in the OPEN statement, sequential files are defaulted to be formatted and
direct access files are defaulted to be unformatted.
A formatted file is read and written with formatted I/O statements. That
is, the READ or WRITE statements contain a format or list-directed
specification.
An unformatted file is read and written with unformatted I/O statements.
That is, the READ and WRITE statements do not contain format
specifications.
For example, in the program below, unit 10 is connected to a formatted
file and unit 11 is connected to an unformatted file. Both files are
sequential access files.
PROGRAM format_unformat
REAL*4 value
INTEGER*4 count
CHARACTER*16 name
DATA value /123.456/
DATA count /123456/
DATA name /'John Doe'/
C Open the formatted and unformatted sequential files:
OPEN(10, FILE='file1', FORM='FORMATTED')
OPEN(11, FILE='file2', FORM='UNFORMATTED')
C Write the data to the formatted file
C (36 bytes will be written):
WRITE(10, '(F10.3, I10, A16)') value, count, name
C Write the 24 data bytes to the unformatted file
C (24 data bytes will be written):
WRITE(11) value, count, name
CLOSE(10)
CLOSE(11)
END
The formatted WRITE statement uses the (F10.3, I10, A16) format
specification, which specifies that 36 characters are to be written to
the disk.
The unformatted WRITE statement writes the data to the file without
conversion. The number of bytes written to the disk correspond to the
number of bytes allocated to the variables in the declaration statement.
In this example, there is a 4-byte real, a 4-byte integer, and a 16-byte
character variable, for a total of 24 bytes. The advantage of the
unformatted WRITE statement is that the numeric data takes up less room
on the disk and that the slow conversion from binary to character format
is not done. For floating point data, using unformatted I/O ensures that
accuracy is not lost by the conversion and rounding process used for
ASCII I/O.
Using the INQUIRE Statement
The INQUIRE statement returns information about a file or unit. The
information returned can be about one of the following:
* A file that is not connected to a unit
* A file that is connected to a unit
* A FORTRAN I/O unit
For example, the statement:
INQUIRE(FILE='abcfile', ERR=999, EXIST=ex, ACCESS=ac)
returns information about the file abcfile to the variables ex and ac.
If an error occurs during the INQUIRE, control transfers to the statement
labeled 999.
Here is another INQUIRE statement:
INQUIRE(FILE='exfile', IOSTAT=ios, ERR=99, EXIST=ex,
* OPENED=iop, NUMBER=num, ACCESS=acc)
This statement requests information on the file exfile. If exfile exists
and is connected to a unit in the program, the variables ex and iop
return the value true. The unit number of the file is stored in num and
the character variable acc is defined.
If the file exfile does not exist, ex and iop return the value false, and
ios is zero if there was no error, or is a system-defined value greater
than zero if there was an error.
The program below opens the file pfile and uses the INQUIRE statement to
return information about the file to the variables ios, iop, ex, and ac.
PROGRAM inquire_info
LOGICAL ex, iop
CHARACTER*10 ac
OPEN(8, FILE='pfile')
INQUIRE(FILE='pfile', IOSTAT=ios, OPENED=iop,
* EXIST=ex, ACCESS=ac, ERR=100)
PRINT *, "iop = ", iop ! iop returns T if the file is opened
PRINT *, "ex = ", ex ! ex returns T if the file exists
PRINT *, "ac = ", ac ! ac returns the type of file access
IF (ios .NE. 0) THEN ! ios returns the I/O status
PRINT *, "ios =", ios
ENDIF
100 CLOSE(8)
END
Because the file pfile exists and successfully opens, the program prints
the following:
iop = T
ex = T
ac = SEQUENTIAL
Similarly, the program below uses the INQUIRE statement to return
information about
unit 8. Note that this INQUIRE statement refers to the connection to I/O
unit 8, not to the file pfile.
PROGRAM inquire_info2
LOGICAL ex, iop
CHARACTER*10 ac
OPEN(8, FILE='pfile')
INQUIRE(UNIT=8, IOSTAT=ios, OPENED=iop,
* EXIST=ex, ACCESS=ac, ERR=100)
PRINT *, ios ! ios returns the I/O status
PRINT *, iop ! iop returns T if the unit is opened
PRINT *, ex ! ex returns T if the unit exists
PRINT *, ac ! ac returns the type of file access
100 CLOSE(8)
END
Because unit 8 is connected, the program prints the following:
0
T
T
SEQUENTIAL
Positioning the File Pointer
The BACKSPACE, REWIND, and ENDFILE statements control the position of the
file pointer within a sequential access file.
The unit specifiers UNIT, IOSTAT, and ERR can be used on the file
positioning statements.
The BACKSPACE Statement.
The BACKSPACE statement positions the file pointer back one record. For
example, the statement:
BACKSPACE 10
moves the file pointer for unit 10 back one record.
The REWIND Statement.
The REWIND statement positions the file pointer at the beginning of the
file. For example, the statement:
REWIND(UNIT=13, IOSTAT=ios, ERR=99)
moves the file pointer to the initial point in the file connected to the
logical unit 13. If an error occurs, the error number is stored in the
variable ios and control transfers to
statement 99.
The ENDFILE Statement.
The ENDFILE statement writes an end-of-file record as the next record.
For example, the statement:
ENDFILE 13
writes an end-of-file record as the next record of the file connected to
unit number 13.
Example of Using the File Positioning Statements.
The file positioning statements are used in the following program:
PROGRAM positioning
INTEGER*4 quantity
REAL*4 price
C Open the file connected to unit 10:
OPEN(10, FILE = 'pfile')
C Read some records:
DO i = 1, 5
READ(10,'(I10, F9.2)') quantity, price
END DO
C Move the file pointer from unit 10 to the previous record:
BACKSPACE 10
C Move the file pointer to the initial point in the file connected
C to logical unit 10.
C If an error occurs, the error number is
C stored in the variable ios and control transfers to statement 99.
REWIND(10, IOSTAT=ios, ERR=99)
C Write an end-of-file record as the next record of the file connected
C to unit number 10:
ENDFILE 10
STOP
C Error handling section:
99 WRITE(6, '("ERROR = ", I6)') ios
END
File Handling Examples
This section demonstrates the use of several options of the file handling
statements.
Computing the Mean of Data in a Sequential File.
The following program computes the mean of all the data items in the disk
file data. The file contains an unknown number of records, with each
record containing one real number.
PROGRAM compute_mean
sum = 0.0 ! Initialize
n = 0 ! Initialize
OPEN(3, IOSTAT = ios, ERR = 99, FILE = 'data',
* ACCESS = 'SEQUENTIAL', STATUS = 'OLD')
10 READ (3, 22, END=88, IOSTAT = ios, ERR = 99) anum
22 FORMAT (F10.5)
sum = sum + anum !Add data entries
n = n + 1 ! Count entries
GO TO 10 ! Loop
C Out of loop
88 avg = sum / n
WRITE(6,33) avg ! Output to preconnected unit 6
33 FORMAT (1X, 'The average is ', F12.6)
CLOSE(3)
STOP
C If there is an error in the OPEN or READ, output to the
C preconnected unit 6.
99 WRITE(6,44) ios
44 FORMAT (1X, 'Error encountered = ', I6)
END
If the file data contains the following:
1.0
2.0
3.0
4.0
the output of the program looks like this:
The average is 2.500000
If the file data does not exist, an error occurs and the error number is
output.
Inserting Data Into a Sorted Sequential File.
This program inserts a single number in the proper position in a sorted
sequential file.
PROGRAM insert_number
C Declare and initialize variables:
IMPLICIT NONE
REAL anum, fnum
INTEGER ios1, ios2, EOF
PARAMETER (EOF = -1)
C Open the files:
OPEN(18, FILE='oldfile', STATUS='UNKNOWN', IOSTAT=ios1, ERR=99)
OPEN(17, FILE='newfile', STATUS='NEW', IOSTAT =ios2, ERR=99)
C Prompt for number to be inserted and begin reading the file:
PRINT *, 'Enter number to be inserted: '
READ *, anum
READ(18, *, END=100, IOSTAT=ios1, ERR=99) fnum
C Copy fnum to 'newfile' until EOF is reached or until fnum >= anum
DO WHILE (fnum .LT. anum)
WRITE(17, *) fnum
READ(18), *, END=100, ERR=99, IOSTAT=ios1) fnum
END DO
C Write the inserted number to 'newfile':
100 WRITE(17, *) anum
C Copy data to 'newfile' until EOF is reached:
DO WHILE(ios1 .NE. EOF)
WRITE(17, *) fnum
READ(18, *, ERR=99, IOSTAT=ios1) fnum
END DO
CLOSE(17)
CLOSE(18)
STOP 'All Done'
C Error handling section
99 WRITE (6, '(1X, "ERROR = ", 2I6)') ios1, ios2
END
If the file oldfile originally contained the following:
1.0
2.0
3.0
4.0
5.0
and you run the program to insert the number 3.5, the file newfile looks
like this after execution:
1.0
2.0
3.0
3.5
4.0
5.0
MPE/iX 5.0 Documentation