Reputation: 137
My question is how to read beginning from the end of a text file. For example,
do
read(1,*) i
print *,i
end do
will read each line in the file 1, and print the contents to the terminal. How would I do this starting from the end of the file?
Upvotes: 2
Views: 2385
Reputation: 1026
You can achieve what you want by using inquire
, access=stream
, and the pos
tag in the read statement. A quick 10 minute exercise gives the following.
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
Save this into a file named foo.f90, compile, and run. Someone here can make it more elegant. Edited original version: don't need to use array sections for s(j)
.
Upvotes: 4
Reputation: 198294
It is not possible. Reading always starts from a certain point, and proceeds forward. By default it starts from the first byte; but you can jump to some other location.
The critical issue is, in a free-format file, there is no way to know where the lines start unless you read the file. You could jump to the last byte, check whether it is a line separator or not, then jump to the byte before it if it wasn't, crawling back till you find a newline, but it would be very inefficient.
A better way would be to read the whole file once, remembering where the newlines were; then iterate this array backwards, jumping to each line's start position to read it. This is not as inefficient, but it is not great, either.
The best way, if you have the memory for it, is to read in the whole file into an array of lines, then reverse the array in-memory.
Upvotes: 2