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