Errors in most executable statements can be prevented by taking sufficient care in writing the program, but in I/O statements errors can be caused by events beyond the control of the programmer: for example through trying to open a file which no longer exists, writing to a disc which is full, or reading a data file which has been created with the wrong format. Since I/O statements are so vulnerable, Fortran provides an error-handling mechanism for them. There are actually two different ways of handling errors which may be used independently or in combination.
Firstly, you can include in the I/O control list an item of the form:
When the statement has executed the integer variable (or array element) will be assigned a value representing the I/O status. If the statement has completed successfully this variable is set to zero, otherwise it is set to some other value, a positive number if an error has occurred, or a negative value if the end of an input file was detected. Since the value of this status code is system-dependent, in portable software the most you can do is to compare it to zero and, possibly, report the actual error code to the user. Thus:
100 WRITE(UNIT=*, FMT=*)'Enter name of input file: ' READ(UNIT=*, FMT=*) FNAME OPEN(UNIT=INPUT, FILE=FNAME, STATUS='OLD', IOSTAT=KODE) IF(KODE .NE. 0) THEN WRITE(UNIT=*,FMT=*)FNAME, ' cannot be opened' GO TO 100 END IFThis simple error-handling scheme makes the program just a little more user-friendly: if the file cannot be opened, perhaps because it does not exist, the program asks for another file-name.
The second method is to include an item of the form
which causes control to be transferred to the statement attached to that label in the event of an error. This must, of course, be an executable statement and in the same program unit. For example:
READ(UNIT=IN, FMT=*, ERR=999) VOLTS, AMPS WATTS = VOLTS * AMPS * rest of program in here . . . . . and finally STOP 999 WRITE(UNIT=*,FMT=*)'Error reading VOLTS or AMPS' ENDThis method has its uses but is open to the same objections as the GO TO statement: it often leads to badly-structured programs with lots of arbitrary jumps.
By using both IOSTAT= and ERR= in the same statement it is possible to find out the actual error number and jump to the error-handling code. The presence of either keyword in an I/O statement will allow the program to continue after an I/O error; on most systems it also prevents an error message being issued.
The ERR= and IOSTAT= items can be used in all I/O statements. Professional programmers should make extensive use of these error-handling mechanisms to enhance the robustness and user-friendliness of their software.
There is one fairly common mistake which does not count as an errors for this purpose: if you write a number to a formatted record using a field width too narrow to contain it, the field will simply be filled with asterisks.
If an error occurs in a data transfer statement then the position of the file becomes indeterminate. It may be quite difficult to locate the offending record if an error is detected when transferring a large array or using a large number of records.