Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28633 Discussions

How do I "stuff" or grab quantites from a file?

WSinc
New Contributor I
510 Views

This file I want to look at has NO PREDEFINED structure, it was

not written by a FORTRAN program. So I have to put a record in

a buffer and read it with DIRECT ACCESS.

Now if the quantity is say REAL*8 in byte position 8, do I

have to do this:

integer*1 buf(2000)

real*8 X

eqivalence (X,Buf(8))

read(10)buf

print *,"x =", x

 

Or is there a "cleaner" way to do it?

Like a copy without a type conversion, for example.

Yet another "dirty" way is using a COMMON block:

COMMON. /FILE10/ buf(7),x

integer*1 buf

real*8 X

But then the READ would normally be in a separate routine,

and the COMMON region would be defined differently to encompass

all the quantities in the buffer.

 

Why do I not use C++? Cause I am lazy,

and have been using Fortran for 50 years.

 

0 Kudos
8 Replies
TimP
Honored Contributor III
510 Views

open(access='stream'...) is the usual route toward working with binary data files written outside of Fortran (or maybe even by differing Fortran implementations).

If you've been using Fortran for 50 years, you shouldn't be getting mixed up between direct and sequential access.

0 Kudos
mecej4
Honored Contributor III
510 Views

Billsincl:

Your use of EQUIVALENCE is not standard-conforming. Therefore, your programs with such code may stop working some day.

According to 16.6.6 1 (1) of the Fortran 2008 standard, 

With the exceptions noted immediately below, when a variable of a given type becomes defined, all associated variables of different type become undefined....

When you define the contents of buf by reading data into it, X becomes undefined even if you had explicitly defined it earlier.

0 Kudos
Paul_Curtis
Valued Contributor I
510 Views

This situation shows up the limitations of standard Fortran file i/o, and is very straightforward to address using the WinAPI file functions (all of which are easily and directly accessed from IVF).  The macguffin here is that the WinAPI functions open a file to a handle, and then allow copying a specified number of bytes between a specific position (offset) in the file and any location in memory, ie your variable, with no intermediate steps or transformations whatever(!).  So for example,

[fortran]

ihandl = open_the_file (filepathname, 'R')

CALL rw_file ('R', ihandl, 8, LOC(x), offset_from_filestart)

[/fortran]

and that's it, 8 bytes from the file starting at the specified offset are copied into your real variable x, couldn't be simpler.  A sample module of IVF WinAPI based file utility functions have been uploaded to this forum, ages ago.  HTH

0 Kudos
John_Campbell
New Contributor II
510 Views

Bill,

You might want to look at the TRANSFER intrinsic function, such as:

x = TRANSFER (buff(8:15), x)

Depending on the source of the file, you might need to manipulate the bytes of buff, to adjust for the endedness of the source of X.
It also provides some flexibility in the location of X in the buffer.

This provides for a sort of standard conforming approach to what is not a standard conforming problem.

John

0 Kudos
IanH
Honored Contributor II
510 Views

An example to provide detail on TimP's suggestion.  This won't account for a difference in endianess or other variation in the representation of a real number and it also assumes that the size of the "file storage unit" is a byte.  But unless you are playing on swings a long way from home these assumptions are pretty safe.

[fortran]INTEGER :: unit
INTEGER, PARAMETER :: position_of_interest = 8
REAL(8) :: value_of_interest
!****
OPEN(NEWUNIT=unit, NAME='name of the file', ACCESS='STREAM', FORM='UNFORMATTED')
READ (unit, POS=position_of_interest) value_of_interest
PRINT *, value_of_interest
CLOSE(unit)

[/fortran]

0 Kudos
WSinc
New Contributor I
510 Views

Thanks for responding -

I will look at both the TRANSFER and the POS approaches. One thing I want to point out is, no matter what

computer was used to make the file, C++ would not solve the problem either, since the number formats

might be totally different. But doesn't the IEEE standard provide a "standard" way to represent integer

and REAL quantities? Also, are the WINAPI functions available in the Fortran library, or is that a separate

library call?

0 Kudos
TimP
Honored Contributor III
510 Views

As IanH pointed out, even if the file is written with IEEE floating point format, endian-ness must be taken into account.  Most current  compilers, including Intel's, have an option to switch byte order on file read. I think VMS (or IBM mainframe) is the most recent major exception to IEEE format and also the most recent one which mixes big- and little-endian.  IEEE standard doesn't apply to integer formats, but those also have been de facto standard for decades.

If you can't be bothered to look up how to use WinAPI functions, that subject is not for you, and it's certainly not a digression which belongs in this thread.

0 Kudos
WSinc
New Contributor I
510 Views

Fortunately, in my case, I only have to worry about one particular source for the files I want to look at, so the conversion issues only have to be addressed once.

As for the WinAPI stuff, I don't mind looking at that, but I am concerned about the complexity of using more than one set of libraries in the same source code.

0 Kudos
Reply