【问题标题】:Fortran formatted stream read a file with new line causes problemsFortran 格式的流读取带有新行的文件会导致问题
【发布时间】:2016-04-07 15:40:44
【问题描述】:

如果我使用 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 

【问题讨论】:

  • PS,OSx 上的 gfortran,截至 1/2016 都是最新的
  • 使用标签fortran,让更多人看到你的问题。仅当您想限制为单个版本(无 F 2008)时才使用这些版本。

标签: fortran


【解决方案1】:

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

使用格式化流,没有 ADVANCE 说明符的读取语句前进到下一条记录,就像带有格式化顺序文件的 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

【讨论】:

    猜你喜欢
    • 2016-08-18
    • 2014-11-16
    • 2016-03-06
    • 1970-01-01
    • 2015-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多