The codes are:
character(100)fin
real(4)a
fin='xx.bin'
open(unit=2,file=fin,status='old',ACCESS='SEQUENTIAL',FORM='UNFORMATTED')
read(2)a
write(*,*)a
close(2)
The file exists
>l xx.bin
-rw-r--r-- 1 -- staff 19353628 May 5 14:01 ./xx.bin
Any clue
The first record in the file (assuming the file is properly
structured
as an unformatted file) could be shorter than the number of bytes that
make up a single real.
While unformatted files can have any structure, depending on the
compiler
used for the program that created the file, most nowadays use the
following scheme:
- Each record starts with 4 bytes indicating the number of bytes of
data
- The same 4 bytes appear after the data bytes
Could the file possible be a _binary_ file? For instance it is written
by a C program, so it is not structured with records and record
markers?
In that case, try ACCESS='STREAM' (a sufficiently modern version of
gfortran supports that F2003 feature)
Regards,
Arjen
You haven't told us the version of the compiler you are using - nor how
you have created the file you are reading (if you used a different
compiler/compiler version to create it, tell us which).
Tobias
Try:
od -x xx.bin | head
-- glen
Unless the file was written by a Fortran program from the same
compiler, "unformatted" will not be able to read the file.
Fortran "unformatted" is not a way to read generic binary
data, but only reads record oriented files with a specific
non-portable structure. To read files from another source
a direct access file with a record length of 1 is possible.
Daniel Feenberg
Well, the situation is not that bad; often a file written with one
Fortran compiler can also be opened using a different compiler - but,
granted, it does not always work. One also need to watch out for endian
differences, if one transfers files from a different platform, but with
compiler options/environment variables, one can usually handle those.
Tobias
> To read files from another source
> a direct access file with a record length of 1 is possible.
Sometimes. There really isn't any completely bullet-proof and portable
method before the access='stream' of f2003. There are multiple
situations in which a record length of 1 won't work.
There are compilers for which the 1 means 1 word instead of 1 byte
(although there tend to be options to change that, at least with recent
compilers).
There are systems where the record length can't be arbitrary (for
example, it might need to be a multiple of the word length) or where
some record lengths imply record padding.
There are compilers where direct access files also have file or record
headers instead of being pure data.
There is also the mess of having to put together the 1-byte pieces after
you have read them. Don't assume that you can, for example, just read a
4-byte real with a record length of 1 byte, causing the compiler to read
4 records. That trick is non-standard and non-portable.
All that being said, things will often, perhaps even usually, work
(assuming you really do read 1 byte at a time and do asembly
separately). But there are enough caveats that I consider it misleading
to imply that it works without qualification.
Stream acess is *MUCH* more straightforward and has far fewer caveats;
that's why it was added.
--
Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain
Try it without the iostat clause. You'll get a more informative message.
Louis
Standard issues with very poorly asked question:
1. What system? GNU Fortran supports many. Which GNU Fortran? G95 and Gfortran
are both "GNU Fortran"s and both claim to be fortran 95.
2. Where did the unformatted file come from? What program wrote it? Do you
really know what "unformatted" means as a Fortran technical adjective? It
is what others call "binary" (but all files are binary on a binary computer so
common descriptions are pretty flakey at best).
3. Have you octal/hex dumped the "unformatted" file to verify that it
follows the
Fortran rule for being an unformatted file. The fortran rules are very strict
to support long records, backspacing, partial reading etc.
4. Did you think you were getting a byte sequential read which is Fortran 2003
and has various names as an extension to earlier versions.
> The file was created by IDL into a binary in Mac Snow Leopard; I am
> reading the file on linux. Endian is the same.
> I don't think there is any first record indicating the number of
> bytes. There are 7*691201 records of 4 bytes --> 19353628 that is the
> file size.
> ----
> Somehow 'sequential' does not work.
That's because what you have is not a Fortran unformatted sequential
file. As others have noted, that is a particular form, which isn't what
you have.
> Maybe I am using F90 (not F2003)
Not pertinent to sequential or direct access. The only relevance to
f2003 is that f2003's stream access is really what you want. Many/most
f90/f95 compilers today do support the f2003 stream facility. I
recommend you pursue that. I don't recall exactly what compiler you are
using (GNU f90 isn't adequately descriptive, as Gordon mentioned). But I
believe that recent versions of both g95 and gFortran do support stream.
>
open(unit=2,file=fin,status='old',ACCESS='stream',FORM='UNFORMATTED',ios
tat=open_status)
> if(open_status>0)stop"unit2 open error"
> > ./mk_07orb_1sec
> STOP unit2 open error
Hmm. As Louis mentioned, taking the iostat out should give a better
message explaining what was wrong with the open. Assuming that the file
does exist and is readable (those assumptions are important; it is easy
to get lead astray on things like that) it might be that you are using
an old enough version of the compiler that it doesn't support stream.
The error message should make that evident, though.
> I tried to read in direct access mode
> integer(4)isec
> real(4)scpos15(3),scvel15(3)
>
>
open(unit=2,file=fin,status='old',ACCESS='direct',FORM='UNFORMATTED',ios
tat=open_status,recl=4)
> if(open_status>0)stop"unit2 open error"
> read(2,rec=1)isec
> read(2,rec=2)scpos15 (this is line 27)
> read(2,rec=5)scvel15
> the first record, isec, is now read correctly, but not the rest
> > ./mk_07orb_1sec
> At line 27 of file mk_07orb_1sec.f90
> Fortran runtime error: Short record on unformatted read
That's because you are trying to read 3 values (12 bytes) from the
second record. The rec=2 doesn't mean to start at the second record and
read as far as needed. It means to read just the second record. Some
compilers have non-portable hacks in this area, in particular, I think
some compilers special-case recl=1 to imply such behavior, but that's
not standard. That's one of the thinks that makes direct access a bit of
a pain for this purpose; doable, but sometimes painful.
character(100) fio
real(4) a(10),b(10)
integer(4) i
do i=1,10
a(i)=i
enddo
fio='./x.bin'
open(4,file=fio,status='replace',form='unformatted')
write(4)a
close(4)
open(2,file=fio,status='old',form='unformatted',access='sequential')
read(2)b
close(2)
write(*,*)b
The usual reason that error is given is that size of the data
being read exceeds the size of the record in the file. As
Arjen said, for most Fortran implementations on UNIX or Unix-like
operating systems, the length is in a four-byte header that
precedes the record. If the variable a is larger than the first
record in the file, then that is your problem.
Bob Corbett
Others suggested reading this file with stream access. However I think
it was written by IDL specifically for direct access. It appears to be
direct access, little endian, record length 28 bytes, with the first
"word" of each record being a default 4-byte integer. I suppose the
other six "words" are default 4-byte reals, but I can't make out the
complete pattern for sure. Your sample code below reinforces this
guess.
You could also read the file as individual 4 byte "words", which is what
I think you are trying to do below. That is more confusing. That way,
you are doing more work keeping track of explicit word offsets for the
integer and six reals within each logical record. The errors you
encountered are a consequence of this. Better I think to make fortran
do that housekeeping for you, just read the file as 691201 logical
records of seven "words" each; one integer and six reals.
One caveat is that the units of "recl=" is not standardized. It may be
in bytes or 4-byte "words". IIRC it is bytes for gfortran on linux, but
I don't remember for sure. There may be a compiler line option to
change that.
> I tried to read in direct access mode
> integer(4)isec
> real(4)scpos15(3),scvel15(3)
>
> open(unit=2,file=fin,status='old',ACCESS='direct',FORM='UNFORMATTED',iostat=open_status,recl=4)
> if(open_status>0)stop"unit2 open error"
> read(2,rec=1)isec
> read(2,rec=2)scpos15 (this is line 27)
> read(2,rec=5)scvel15
> the first record, isec, is now read correctly, but not the rest
> > ./mk_07orb_1sec
> At line 27 of file mk_07orb_1sec.f90
> Fortran runtime error: Short record on unformatted read
Try the following, change recl from 28 to 7 if necessary (probably
not). Note that I made your variables to be default integers and
reals. This assumes the most likely scenario that your compiler uses
default 4-byte integers and reals. Explicit kind numbers e.g.
integer(4) are another can of worms for a different conversation.
integer isec
real scpos15(3), scvel15(3)
open(unit=2,file=fin,status='old',ACCESS='direct', &
iostat=open_status,recl=28)
if(open_status>0)stop"unit2 open error"
read (2,rec=1) isec, scpos15, scvel15
Subsequent record numbers go from 2 to 691201, incrementing by 1.
Stream access will also get the job done. Call it style, but I prefer
direct access for files that were constructed for that purpose in the
first place.
--Dave