8

I have a binary file that I would like to read with Fortran. The problem is that it was not written by Fortran, so it doesn't have the record length indicators. So the usual unformatted Fortran read won't work.

I had a thought that I could be sneaky and read the file as a formatted file, byte-by-byte (or 4 bytes by 4 bytes, really) into a character array and then convert the contents of the characters into integers and floats via the transfer function or the dreaded equivalence statement. But this doesn't work: I try to read 4 bytes at a time and, according to the POS output from the inquire statement, the read skips over like 6000 bytes or so, and the character array gets loaded with junk.

So that's a no go. Is there some detail in this approach I am forgetting? Or is there just a fundamentally different and better way to do this in Fortran? (BTW, I also tried reading into an integer*1 array and a byte array. Even though these codes would compile, when it came to the read statement, the code crashed.)

2 Answers 2

11

Yes.

Fortran 2003 introduced stream access into the language. Prior to this most processors supported something equivalent as an extension, perhaps called "binary" or similar.

Unformatted stream access imposes no record structure on the file. As an example, to read data from the file that corresponds to a single int in the companion C processor (if any) for a particular Fortran processor:

USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_INT
INTEGER, PARAMETER :: unit = 10
CHARACTER(*), PARAMETER :: filename = 'name of your file'
INTEGER(C_INT) :: data
!***
OPEN(unit, filename, ACCESS='STREAM', FORM='UNFORMATTED')
READ (unit) data
CLOSE(unit)
PRINT "('data was ',I0)", data

You may still have issues with endianess and data type size, but those aspects are language independent.

If you are writing to a language standard prior to Fortran 2003 then unformatted direct access reading into a suitable integer variable may work - it is Fortran processor specific but works for many of the current processors.

Sign up to request clarification or add additional context in comments.

7 Comments

Works great! Thanks! And I thought I was just about getting good with FORTRAN 90. And now more to learn! Ah well. Many thanks.
Without the "stream" access the Fortran read was interpreting some data as length-of-record information. Which both skipped data that you wanted to read and caused the record lengths to be wrong. Plus the file doesn't really have records in the Fortran sense.
@M.S.B.: If, as the OP indicated, he first tried with formatted read, my guess is that it scanned forwards until it hit a newline character.
@janneb, yes. On a normal formatted read Fortran would fill the requested string then discard the rest of the record. Which you could override by using formatted stream IO!
@M. S. B. Non-advancing input is what would be needed to avoid discarding the rest of the record. Advancing formatted stream positions the file after the record just read in the same manner as advancing formatted sequential. Both formatted stream and formatted sequential have issues with returning byte patterns that look like newlines and/or record separators.
|
0

Watcom Fortran 77: use form='unformatted' and recordtype='fixed' in the open statement. You can read any amount any time without losing any bytes - also works for writing a file. I use it all the time.

2 Comments

There is no recordtype in Fortran 77. Probably some nonstandard extension of some particular compiler. In standard Fortran one could try direct access with a single character in the record, but that could only work if recirds are counted in bytes, not in larger words.
The comment says that it's specific to Watcom Fortran '77.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.