Fortran正在阅读超出endfile记录 [英] Fortran is reading beyond endfile record

查看:309
本文介绍了Fortran正在阅读超出endfile记录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图从一个文件中读取一些数据,并且结束文件记录检测对于停止阅读很重要。但是,根据用于读取数据的数组的数组维数,我无法正确检测到最终文件记录,并且我的Fortran程序停止。



该程序如下所示:

 !integer,dimension(3):: x!第1.1行
!integer,dimension(3,10):: x!第1.2行
整数,维(10,3)::!第1.3行
integer :: status,i = 1
字符(len = 100)::错误

open(30,file ='data.dat',status =' (',',iostat = status,iomsg = error)x!第2.1行
!read(30,*,iostat = status,iomsg = error)x(:,i)!第2.2行
read(30,*,iostat = status,iomsg = error)x(i,:)!第2.3行
$ b $ if 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行未被注释时出现上述错误:


error cod:5008



错误信息: ENDFILE记录

然而,使用第1.1和2.1行或第1.2和2.2行,程序工作,检测endfile记录。



所以,我想了解一些帮助,了解为什么我不能使用第1.3行和第2.3行来正确读取此文件,因为我给出读取命令的数组元素的正确数量。

我使用的是gfortran编译器,6.3.0版。



编辑:更简单的例子



以下产生5008读取ENDFILE记录错误:

<$ p (20,*,iostat = 0)$ b $ open(20,file ='noexist')
read(20,*,iostat = s)x
write(*,*)s
end

如果我们使 x 标量或一个d数组(任意大小),我们得到预期的 -1 EOF标志。如果文件实际不存在或为空则无关紧要。如果文件包含一些,但数据不足,则很难理解您可能得到的返回值。 / div>

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

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



更新:我已经证实,这不会发生在英特尔的ifort。 gfortran之前似乎也遇到了类似问题:阅读时错误的IOSTAT值NAMELISTs过去EOF 。这是否是一个错误是值得商榷的。代码当然看起来应该陷入EOF。


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.

解决方案

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.

这篇关于Fortran正在阅读超出endfile记录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆