Fortran is reading beyond endfile record

2019-04-08 14:22发布

I'm trying to read some data from a file, and the endfile record detection is important to stop reading. However, depending of the array dimensions of the array used to read data, I cannot detect properly the endfile record and my Fortran program stops.

The program is below:

!integer, dimension(3) :: x                      ! line 1.1
!integer, dimension(3,10) :: x                   ! line 1.2
integer, dimension(10,3) ::                      ! line 1.3
integer :: status,i=1
character(len=100) :: error

open( 30, file='data.dat', status='old' )
do
  print *,i
  !read( 30, *, iostat=status, iomsg=error ) x          ! line 2.1
  !read( 30, *, iostat=status, iomsg=error ) x(:,i)     ! line 2.2
  read( 30, *, iostat=status, iomsg=error ) x(i,:)      ! line 2.3

  if ( status < 0 ) then        print *,'EOF'
    print *,'total of ',i-1,' lines read.'
    exit
  else if ( status > 0 ) then
    print *,'error cod: ',status
    print *,'error message: ', error
    stop
  else if ( status == 0 ) then
    print *,'reading ok.'
    i = i + 1
  end if
end do

With 'data.dat' file been:

10 20 30
30 40 50

When lines 1.3 and 2.3 are uncommented the mentioned error appears:

error cod: 5008

error message: Read past ENDFILE record

However, using lines 1.1 and 2.1, or 1.2 and 2.2, the program works, detecting endfile record.

So, I would like some help on understanding why I cannot use lines 1.3 and 2.3 to read properly this file, since I'm giving the correct number of array elements for read command.

I'm using gfortran compiler, version 6.3.0.

EDIT: simpler example

the following produces a 5008 "Read past ENDFILE record" error:

implicit none
integer x(2,2),s
open(20,file='noexist')
read(20,*,iostat=s)x
write(*,*)s
end

if we make x a scalar or a one-d array ( any size ) we get the expected -1 EOF flag. It doesn't matter if the file actually doesn't exist or is empty. If the file contains some, but not enough, data its hard to make sense of which return value you might get.

2条回答
贼婆χ
2楼-- · 2019-04-08 14:22

Please note this is only a guess. Remember that Fortran stores arrays in column major order. When gfortran compiles read() x(:,i), the 3 memory locations are next to each other so in the executable, it produces a single call to the operating system to read in 3 values from the file.

Now when read() x(i,:) is compiled, the three data elements x(i,1), x(i,2) and x(i,3) are not in contiguous memory. So I am guessing the executable actually has 3 read calls to the operating system. The first one would trap the EOF but the 2nd one gives you the read past end of file error.

UPDATE: I have confirmed that this does not occur with Intel's ifort. gfortran seems to have had a similar problem before: Bad IOSTAT values when readings NAMELISTs past EOF. Whether this is a bug or not is debatable. The code certainly looks like it should trap an EOF.

查看更多
我只想做你的唯一
3楼-- · 2019-04-08 14:35

I am not sure if I am expressing myself correctly but it has to do with the way fortran is reading and storing 2d-arrays. When you are using this notation: x(:,i), the column i is virtually expanded in-line and the items are read using this one line of code. In the other case where x(i,:) is used, the row i is read as if you called read multiple times. You may use implied loops if you want to stick with a specific shape and size. For example you could use something like that:read( 30, *, iostat=status, iomsg=error ) (x(i,j), j=1,3)

In any case you should check that your data are stored properly (as expected at least) in variable x.

查看更多
登录 后发表回答