Fortran正在读取endfile记录之外的内容

时间:2018-03-02 13:58:14

标签: fortran gfortran eof data-files

我正在尝试从文件中读取一些数据,并且结束文件记录检测对于停止读取非常重要。但是,根据用于读取数据的数组的数组维度,我无法正确检测到endfile记录,并且我的Fortran程序会停止。

该计划如下:

!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

使用'data.dat'文件:

10 20 30
30 40 50

当取消注释第1.3和2.3行时,会出现上述错误:

  

错误编号:5008

     

错误消息:读取过去的ENDFILE记录

但是,使用第1.1和2.1行,或1.2和2.2,程序可以正常工作,检测结束文件记录。

所以,我想帮助理解为什么我不能使用第1.3和2.3行来正确读取这个文件,因为我为读命令提供了正确数量的数组元素。

我正在使用gfortran编译器,版本6.3.0。

编辑:更简单的例子

以下产生5008“读过去ENDFILE记录”错误:

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

如果我们使x为标量或一维数组(任意大小),我们会得到预期的-1 EOF标志。文件实际上不存在或为空是无关紧要的。如果文件中包含 some ,但还不够,那么很难弄清楚您可能获得的返回值。

2 个答案:

答案 0 :(得分:-1)

我不确定我是否正确表达自己,但它与fortran读取和存储2d阵列的方式有关。当您使用此表示法时x(:,i),列i实际上是在线扩展的,并且使用这一行代码读取项目。在使用x(i,:)的另一种情况下,行i的读取就像您多次调用read一样。 如果你想坚持特定的形状和大小,你可以使用隐含的循环。例如,您可以使用类似的内容:read( 30, *, iostat=status, iomsg=error ) (x(i,j), j=1,3)

在任何情况下,您都应该检查您的数据是否已在变量x中正确存储(至少符合预期)。

答案 1 :(得分:-1)

请注意,这只是猜测。请记住,Fortran按列主要顺序存储数组。当gfortran编译read() x(:,i)时,3个内存位置彼此相邻,因此在可执行文件中,它会对操作系统产生一次调用,从文件中读取3个值。

现在编译read() x(i,:)时,三个数据元素x(i,1)x(i,2)x(i,3)不在连续的内存中。所以我猜测可执行文件实际上有3个读操作系统调用。第一个会捕获EOF,但第二个会给你读取文件错误的结尾。

更新:我已经确认英特尔的ifort不会发生这种情况。 gfortran之前似乎遇到过类似的问题:Bad IOSTAT values when readings NAMELISTs past EOF。这是否是一个错误是值得商榷的。代码看起来肯定会陷入EOF。