如果我使用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关联的格式规范,您将丢弃除第一个字符读取之外的所有字符,但基础文件位置仍会更改.
因为你有一个带有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