error-handlingfile-iofortran

Is there an alternative to the err specifier in a Fortran read() statement?


In this code

read(unit,'I0',err=100) my_integer
100 error_stop "Something went wrong."

the err specifier tells the program to go to the statement labeled 100 if something went wrong in reading an integer in from the file with unit identifier unit.

Is there an alternative to this kind of error handling? I know certain workarounds, like using inquire to find out if a file exists or other ways of detecting an end of file. But for a case like this where I try to read in an integer and for whatever reason it can't, is there another way to catch that error?

I ask because it seems somewhat obsolete to be using statement labels. Perhaps this is me just assuming so because goto statements are considered obsolete. Please correct me if I'm wrong.


Solution

  • (Nearly) all of Fortran's input/output statements take the iostat= and iomsg= specifiers.1

    If there is no error condition, end-of-file condition, or end-of-record condition in an input/output statement, any such iostat= specifier means the status variable is defined to be 0. Equally, any such iomsg= specifier leaves the corresponding variable unchanged.2

    The READ statement of the question could, at its most basic, look like (noting two corrections to the format):

    read(unit,'(I5)',iostat=status) my_integer
    if (status/=0) error stop "Something went wrong reading an integer"
    

    However, err= means the execution flow jumps on an error condition, whereas status could be non-zero and indicate an end-of-file condition (corresponding to end=). The intrinsic module ISO_FORTRAN_ENV provides the IOSTAT_END constant which can be used to test whether there was an end-of-file condition and no error condition:

    read (..., iostat=status, ...)  ... 
    if (status/=0) then
       if (status==IOSTAT_EOR) error stop "End-of-record condition in the input"
       if (status==IOSTAT_END) error stop "End-of-file condition in the input"
       error stop "Error condition in the input"
    end if
    

    Recall that end-of-record conditions (corresponding to EOR=) occur only in non-advancing reads.

    Input/output status numbers are essentially meaningless. The iomsg= is more helpful to humans but still cannot be relied on.


    1 The PRINT statement, unlike the WRITE statement, takes no control information list; one form of the READ statement takes no control information list. The other form of the READ statement, the BACKSPACE, CLOSE, ENDFILE, FLUSH, INQUIRE, OPEN, REWIND, WAIT and WRITE all accept the specifiers.

    2 To be precise, this means that both the definition status remains unchanged and the value, if any, remains unchanged. If you're going to rely on testing the value of the IO message, be sure to define it before the input/output statement.