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

时间:2016-01-04 03:04:12

标签: 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 

1 个答案:

答案 0 :(得分:2)

我认为您所看到的是编译器运行时的问题,而您对程序的选择会加剧。

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

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

但是你没有必要在文件中不断跳回和转发 - 而是在读取文件的初始点(可能使用REWIND)之前,然后使用没有POS说明符的非前进输入逐个逐字逐句地逐步执行文件。当到达特定记录的末尾时,您需要适当地处理IOSTAT_EOR状态代码。

另请注意,对于格式化流,无法保证(取决于处理器)所有正整数对应于文件中的有效位置(F2008 9.3.3.4p4项目符号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