Fortran ftell 返回错误位置

Fortran ftell returning to wrong position

这是一段简单的代码,它从文件中读取行,然后 returns 到上一个位置并重新读取同一行:

program main
  implicit none
  integer         :: unit, pos, stat
  character(128)  :: buffer

  ! Open file as formatted stream
  open( NEWUNIT=unit, FILE="data.txt", ACCESS="stream", FORM="formatted", STATUS="old", ACTION="read", IOSTAT=stat )
  if ( stat /= 0 ) error stop

  ! Skip 2 lines
  read (unit,*) buffer
  read (unit,*) buffer

  ! Store position
  pos = ftell(unit)

  ! Read & write next line
  read (unit,*) buffer
  write (*,*) "buffer=", trim(buffer)

  ! Return to previous position
  call fseek(unit,pos,0)
  ! pos = ftell(unit)   ! <-- ?!

  ! Read & write next line (should be same output)
  read (unit,*) buffer
  write (*,*) "buffer=", trim(buffer)

  ! Close file stream
  close (UNIT=unit)

end program main

“data.txt”只是一个包含 4 行的虚拟文件:

1
2
3
4

现在,当我编译代码片段 (gfortran 9.3.0) 并 运行 它时,我得到了一个答案:

 buffer=3
 buffer=4

这是错误的,因为它们应该是一样的。更有趣的是,当我在 'fseek' 之后添加一个额外的 ftell (代码段中的注释行)时,我得到了正确答案:

 buffer=3
 buffer=3

知道为什么会这样吗?还是我使用 ftellfseek 不正确?

gfortran 的 FTELLFSEEK 文档明确指出提供这些例程是为了向后兼容 g77。由于您的代码使用 NEWUNITERROR STOPSTREAM 访问权限,因此您没有编译旧的发霉代码。您应该使用@Vladimir 指出的符合标准的方法。

快速调试会话显示 FTELLFSEEK 对文件位置使用基于 0 的引用,而现代 Fortran 的 inquire 方法是基于 1 的。 gfortran 中可能存在一个 off-by-one 类型错误,但由于 FTELLFSEEK 是为了向后兼容 g77(一个未维护的 15 岁以上编译器),有人需要做一些代码探索以确定预期的行为。我怀疑 none 当前活跃的 gfortran 开发人员足够关心探索这个问题。所以,解决你的问题

program main

  implicit none

  integer pos, stat, unit
  character(128) buffer

  ! Open file as formatted stream
  open(NEWUNIT=unit, FILE="data.txt", ACCESS="stream", FORM="formatted", &
  &  STATUS="old", ACTION="read", IOSTAT=stat)

  if (stat /= 0) stop

  ! Skip 2 lines
  read (unit,*) buffer
  read (unit,*) buffer

  ! Store position
  inquire(unit, pos=pos)

  ! Read & write next line
  read (unit,*) buffer
  write (*,*) "buffer=", trim(buffer)

  ! Reread & write line (should be same output)
  read (unit,*,pos=pos) buffer
  write (*,*) "buffer=", trim(buffer)

  ! Close file stream
  close (UNIT=unit)

end program main