Hi Neil
I was surprised when trying your code out
and getting the same sort of results as you.
Before reading section 9.11 of the 2008 standard I expected
answer 1 rather than answer 2.
I got the first answer with gfortran, nag and oracle/sun
and the second with intel.
The following is a work around, based on switching
to a one character buffer for the incomplete
last read. I don't know if this of any use to you.
Cheers
Ian
program main
use,intrinsic :: iso_fortran_env
integer, parameter :: unit = 10
character :: buffer(8)
character :: onechar
integer buflen, last_pos, curr_pos, ios
!! Create a file to read.
open(unit,file='input.txt',access='stream',
action='write',status='replace')
write(unit) 'abcdefghijkl'
close(unit)
open(unit,file='input.txt',access='stream',action='read')
inquire(unit,pos=last_pos)
print *, 'initial stream position=', last_pos
!! Read the file in 8-character chunks.
do
print *, 'reading into 8-character buffer...'
read(unit,iostat=ios) buffer
if (ios /= 0 .and. ios /= iostat_end) then
print *, 'read error: iostat=', ios
exit
end if
inquire(unit,pos=curr_pos)
buflen = curr_pos - last_pos
print *, 'current stream position=', curr_pos, ', buffer length=',
buflen
last_pos = curr_pos
if (buflen > 0) then
print *, 'buffer=', buffer(:buflen)
else
do
print *, 'attempting reading into 1-character buffer...'
read(unit,iostat=ios) onechar
if (ios == iostat_end) then
print *,' end of file reached'
exit
end if
inquire(unit,pos=curr_pos)
buflen = curr_pos - last_pos
print *, 'current stream position=', curr_pos, ', buffer length=',
buflen
last_pos = curr_pos
print *, 'print one character'
print *, onechar
end do
end if
if (ios == iostat_end) exit
end do
end program
From: Fortran 90 List [mailto:[log in to unmask]] On Behalf Of
Neil Carlson
Sent: 13 October 2012 03:16
To: [log in to unmask]
Subject: EOF encountered during stream input: what happens?
I've got some code that does stream input, reading a chunk into a buffer and
then passing it on to a C library where stuff happens. At some point it
encounters
the EOF and the buffer is partially filled, but I'm able to determine how
much is
in the buffer (using IOSTAT and INQUIRE with the POS keyword) and all is
fine.
This works fine with at least 3 compilers, but this one new compiler (that
has
all kinds of problems) is behaving very differently. On the read that
encounters
the EOF, the buffer is returned empty and the stream position is not
advanced.
A little program that illustrates this is at the end. Here's the output I
expect
to see (and have seen until now):
initial stream position= 1
reading into 8-character buffer...
current stream position= 9 , buffer length= 8
buffer=abcdefgh
reading into 8-character buffer...
current stream position= 13 , buffer length= 4
buffer=ijkl
But with this new compiler:
initial stream position= 1
reading into 8-character buffer...
current stream position= 9 , buffer length= 8
buffer=abcdefgh
reading into 8-character buffer...
current stream position= 9 , buffer length= 0
buflen=0, dumping contents of entire buffer
buffer=
I desperately want to report this as a bug, but searching the standard I'm
starting
to have to some doubts that maybe this is the correct behavior (much to my
consternation).
9.11.3 (3) says "If an end-of-file condition occurs during execution of an
input/output statement
that contains either an END= specifier or an IOSTAT= specifier, and an error
condition
does not occur then: if the statement is a READ statement [...] all input
list items or namelist
group objects in the statement that initiated the transfer become
undefined". Does this refer to
the buffer array as a whole (my case) or to the particular element of the
array, and all subsequent
ones, that was being read when the EOF was encountered? It looks to me that
this one
compiler thinks it means all items listed in the read statement.
Thanks for any thoughts you might have.
-Neil
program main
use,intrinsic :: iso_fortran_env
integer, parameter :: unit = 10
character :: buffer(8)
integer buflen, last_pos, curr_pos, ios
!! Create a file to read.
open(unit,file='input.txt',access='stream',
action='write',status='replace')
write(unit) 'abcdefghijkl'
close(unit)
open(unit,file='input.txt',access='stream',action='read')
inquire(unit,pos=last_pos)
print *, 'initial stream position=', last_pos
!! Read the file in 8-character chunks.
do
print *, 'reading into 8-character buffer...'
read(unit,iostat=ios) buffer
if (ios /= 0 .and. ios /= iostat_end) then
print *, 'read error: iostat=', ios
exit
end if
inquire(unit,pos=curr_pos)
buflen = curr_pos - last_pos
print *, 'current stream position=', curr_pos, ', buffer length=',
buflen
last_pos = curr_pos
if (buflen > 0) then
print *, 'buffer=', buffer(:buflen)
else
print *, 'buflen=0, dumping contents of entire buffer'
print *, 'buffer=', buffer(:buflen)
end if
if (ios == iostat_end) exit
end do
end program
|