Fortran 格式的流读取带有新行的文件会导致问题

标签 fortran

如果我使用 Fortran 以与流相同的方式写入和读取文件,它运行良好。如果我使用文本编辑器编辑文件而不更改任何内容(例如返回然后退格)并保存文件,它将不会读取,在我希望它结束​​的位置之前引用文件结尾。

为了进行调查,我编写了以下代码,该代码写入我的表格,然后将其作为字符一次读取一个位置。只有在我正在读取的文件中没有新行时,它才能正常工作。否则,我只会得到最后 n 个数字,n 是每行的数据量。

这个想法是学习比顺序读取更强大的方法来读取我在工作中使用的来自工程软件和测试设备的大型奇怪格式的数据文件。

program stream
implicit none

character(len=1)                :: text
integer(kind=4), dimension(100) :: array
integer(kind=4)                 :: status = 0, i



open (unit=11, file='out.txt', form='formatted', access='stream', action='readwrite', status='replace')

array = (/(i, i = 1,100)/)           !  Populate vector from 1 to 100

write(unit=11,fmt='(10i4)') array    !  Write array to file

i=0
do while ( status == 0)              !  Read array back from file, one position at a time until end of file
i=i+1
read(unit=11, fmt='(a1)', pos=i, iostat=status) text
write(*,fmt='(a1)', advance='no') text  !  Write results to screen to see what is in each position
end do


close(unit=11)


end program stream

    File written then read:
       1   2   3   4   5   6   7   8   9  10
      11  12  13  14  15  16  17  18  19  20
      21  22  23  24  25  26  27  28  29  30
      31  32  33  34  35  36  37  38  39  40
      41  42  43  44  45  46  47  48  49  50
      51  52  53  54  55  56  57  58  59  60
      61  62  63  64  65  66  67  68  69  70
      71  72  73  74  75  76  77  78  79  80
      81  82  83  84  85  86  87  88  89  90
      91  92  93  94  95  96  97  98  99 100

    Result: (many spaces here)
8   8   8   8   8   8   8   8   9    91  92  93  94  95  96  97  98  99 100 

最佳答案

我认为您看到的是编译器运行时的问题,您对程序所做的选择使问题更加严重。

对于格式化流,没有 ADVANCE 说明符的读取语句前进到下一条记录,就像带有格式化顺序文件的 READ 一样。由于与 READ 相关联的格式规范,因此您将丢弃除第一个读取的字符以外的所有字符,但基础文件位置仍会更改。

因为您有一个带有 READ 的 POS 说明符,所以每个 READ 都需要运行时从记录的末尾向后移动到您感兴趣的下一个字符。编译器的运行时未正确处理此问题。

但是您不需要在文件中不断地前后跳转 - 相反,在读取文件之前将其重新定位在其初始点(可能使用 REWIND),然后使用没有 POS 说明符的非前进输入逐步通过逐个字符的文件。当到达特定记录的末尾时,您将需要适本地处理 IOSTAT_EOR 状态代码。

另请注意,对于格式化流,不能保证(取决于处理器)所有正整数都对应于文件中的有效位置(F2008 9.3.3.4p4 bullet 5,另见注释 9.10)。这是为了适应使用多个文件位置的文件结构,例如记录结束标记(例如,他们可能使用 CR-LF)。

(我注意到您还假设默认 CHARACTER 占用一个文件存储单元 - 这也取决于处理器。)

program stream
  implicit none

  character(len=1)                :: text
  integer(kind=4), dimension(100) :: array
  integer(kind=4)                 :: status = 0, i

  open(  &
      unit=11,  &
      file='out.txt',  &
      form='formatted',  &
      access='stream',  &
      action='readwrite',  &
      status='replace' )

  array = [(i, i = 1,100)]           !  Populate vector from 1 to 100

  write (unit=11, fmt='(10i4)') array    !  Write array to file

  rewind 11
  do
    read (unit=11, fmt='(a1)', iostat=status, advance='no') text
    if (is_iostat_eor(status)) then
      write (*, fmt="()")
      cycle
    else if (status /= 0) then
      exit
    end if
    write (*,fmt='(a1)', advance='no') text  !  write results to screen to see what is in each position
  end do

  close(unit=11)

end program stream

关于Fortran 格式的流读取带有新行的文件会导致问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34584164/

相关文章:

c - 用 C 写入未格式化的直接访问二进制文件

oop - Fortran 2003 seg 错误并覆盖类型绑定(bind)过程

function - Fortran 元素函数 - 这种行为正常吗?

function - 具有假定形状虚拟参数的过程必须具有显式接口(interface)

fortran - 为什么 OpenMP SIMD 指令会降低性能?

function - Fortran 函数中带有可选参数的段错误

algorithm - 将 VBA 代码转换为 Fortran

fortran - Fortran 90 中的优化例程

compiler-errors - 错误: Can't open included file 'math.h'

memory-management - gfortran傻瓜版:mcmodel = medium到底能做什么?