HP 3000 Manuals

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 .

[FFN6]
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 .
[FFN7]
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 .
[FFN8]
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