在 Fortran 90 中从文件末尾读取
Read from end of file in Fortran 90
我的问题是如何从文本文件的末尾开始阅读。
例如,
do
read(1,*) i
print *,i
end do
将读取文件 1 中的每一行,并将内容打印到终端。我如何从文件末尾开始执行此操作?
这是不可能的。阅读总是从某一点开始,并向前推进。默认情况下,它从第一个字节开始;但你可以跳转到其他位置。
关键问题是,在自由格式文件中,除非您阅读文件,否则无法知道行从何处开始。你可以跳到最后一个字节,检查它是否是行分隔符,如果不是,则跳到它之前的字节,爬回直到找到换行符,但效率很低。
更好的方法是读取整个文件一次,记住换行符的位置;然后向后迭代这个数组,跳转到每一行的开始位置来读取它。这不是那么低效,但也不是很好。
如果您有足够的内存,最好的方法是将整个文件读入一个行数组,然后在内存中反转数组。
您可以通过在读取语句中使用 inquire
、access=stream
和 pos
标记来实现您想要的。 10 分钟的快速练习给出以下结果。
program foo
implicit none
integer fd, i, j, m, n
character, allocatable :: s(:)
character :: c
open(newunit=fd,file='foo.f90',access='stream',status='old', &
position='append')
inquire(fd, pos=n)
allocate(s(n))
m = 1
do i = n-1, 1, -1
read(fd, pos=i) c
s(m:m) = c
if (iachar(c) == 10) then
do j = m, 1, -1
write(*,'(A1)',advance='no') s(j)
end do
m = 1
else
m = m + 1
end if
end do
write(*,*)
do j = m-1, 1, -1
write(*,'(A1)',advance='no') s(j)
end do
write(*,*)
close(fd)
end program foo
将其保存到名为 foo.f90 的文件中,编译,然后 运行。这里有人可以让它更优雅。编辑后的原始版本:不需要为 s(j)
.
使用数组部分
我的问题是如何从文本文件的末尾开始阅读。 例如,
do
read(1,*) i
print *,i
end do
将读取文件 1 中的每一行,并将内容打印到终端。我如何从文件末尾开始执行此操作?
这是不可能的。阅读总是从某一点开始,并向前推进。默认情况下,它从第一个字节开始;但你可以跳转到其他位置。
关键问题是,在自由格式文件中,除非您阅读文件,否则无法知道行从何处开始。你可以跳到最后一个字节,检查它是否是行分隔符,如果不是,则跳到它之前的字节,爬回直到找到换行符,但效率很低。
更好的方法是读取整个文件一次,记住换行符的位置;然后向后迭代这个数组,跳转到每一行的开始位置来读取它。这不是那么低效,但也不是很好。
如果您有足够的内存,最好的方法是将整个文件读入一个行数组,然后在内存中反转数组。
您可以通过在读取语句中使用 inquire
、access=stream
和 pos
标记来实现您想要的。 10 分钟的快速练习给出以下结果。
program foo
implicit none
integer fd, i, j, m, n
character, allocatable :: s(:)
character :: c
open(newunit=fd,file='foo.f90',access='stream',status='old', &
position='append')
inquire(fd, pos=n)
allocate(s(n))
m = 1
do i = n-1, 1, -1
read(fd, pos=i) c
s(m:m) = c
if (iachar(c) == 10) then
do j = m, 1, -1
write(*,'(A1)',advance='no') s(j)
end do
m = 1
else
m = m + 1
end if
end do
write(*,*)
do j = m-1, 1, -1
write(*,'(A1)',advance='no') s(j)
end do
write(*,*)
close(fd)
end program foo
将其保存到名为 foo.f90 的文件中,编译,然后 运行。这里有人可以让它更优雅。编辑后的原始版本:不需要为 s(j)
.