Fortran正在读取endfile记录之外的内容
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Fortran正在读取endfile记录之外的内容相关的知识,希望对你有一定的参考价值。
我正在尝试从文件中读取一些数据,并且结束文件记录检测对于停止读取非常重要。但是,根据用于读取数据的数组的数组维度,我无法正确检测到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行来正确读取这个文件,因为我给了read命令正确数量的数组元素。
我正在使用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标志。文件实际上不存在或为空是无关紧要的。如果文件包含一些但不够的数据,则很难理解您可能获得的返回值。
我不确定我是否正确表达自己,但它与fortran读取和存储2d阵列的方式有关。当您使用这种表示法:x(:,i)
时,列i
实际上是在线扩展的,并且使用这一行代码读取项目。在使用x(i,:)
的另一种情况下,读取行i
就好像你多次调用read
一样。如果你想坚持特定的形状和大小,你可以使用隐含的循环。例如,您可以使用类似的东西:read( 30, *, iostat=status, iomsg=error ) (x(i,j), j=1,3)
在任何情况下,您都应该检查您的数据是否在变量x
中正确存储(至少可以预期)。
请注意,这只是猜测。请记住,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。
以上是关于Fortran正在读取endfile记录之外的内容的主要内容,如果未能解决你的问题,请参考以下文章