4

Preface: I needed to figure out the structure of a binary grid_data_file. From the Fortran routines I figured that the first record consists of 57 bytes and has information in the following order.

No. of the file :: integer*4 File name :: char*16 file status :: char*3 (i.e. new, old, tmp) .... so forth (rest is clear from write statement in the program) 

Now for the testing I wrote a simple program as follows: (I haven't included all the parameters)

Program testIO implicit none integer :: x, nclat, nclon character :: y, z real :: lat_gap, lon_gap, north_lat, west_lat integer :: gridtype open(11, file='filename', access='direct', form='unformatted', recl='200') read(11, rec=1) x,y,z,lat_gap,lon_gap, north_lat,west_lat, nclat, nclon, gridtyp write(*,*) x,y,z,lat_gap,lon_gap, north_lat,west_lat, nclat, nclon, gridtyp close(11) END 

To my surprise, when I change the declaration part to

 integer*4 :: x, nclat, nclon character*16 :: y character*3 :: z real*4 :: lat_gap, lon_gap, north_lat, west_lat integer*2 :: gridtype 

It gives me SOME correct information, albeit not all! I can't understand this. It would help me to improve my Fortran knowledge if someone explains this phenomenon.

Moreover, I can't use ACCESS=stream due to machine being old and not supported, so I conclude that above is the only possibility to figure out the file structure.

10
  • The record length for direct access should not be entered directly, like your 200. The processor doesn't have to use bytes as the unit of length, the inquire statement should be used to get it. Also, why do you use 200 when you stated before it is 57 bytes? Commented Jul 30, 2014 at 13:39
  • BTW, there is no mod or admin who does the downvoting, it is the feedback of all the users among themselves. When you get enough reputation you will also be able to vote to other questions and answers. Also, don't get angry for just one downvote, that happens. Try to find out what could motivate it. Many users are afraid of telling you why they voted down the post, because there are some users who take revenge against them. Commented Jul 30, 2014 at 13:43
  • You are absolutely right Vladimir. That's what I did in the beginning. before open statement i used INQUIRE(file=filename, recl=irec) before open statement, but it gave me an error. RECL specifier is zero or negative Commented Jul 30, 2014 at 14:03
  • 1
    Also, on downvoting, I don't feel anger or anything. It is just frustrating. Anyway, I feel like a noob and then comes a downvoting on your question, which just enhances the noob feeling! Plus without a note, you even don't get chance to improve nor does it guarantee that OP wouldn't make same mistake again in the future! It's a vicious circle, you know! Commented Jul 30, 2014 at 14:07
  • You cannot get the length from the file, you have to get it from the variables that are written in the record INQUIRE(iolength=irec) x,y,z,lat_gap,lon_gap, north_lat,west_lat, nclat, nclon, gridtyp Commented Jul 30, 2014 at 14:14

1 Answer 1

2

From your replies and what others have commented, I think your problem might be a misunderstanding of what a Fortran "record" is:

You say that you have a binary file where each entry (you said record, but more on that later) is 57 bytes.

The problem is that a "record" in Fortran I/O is not what you would expect it is coming from a C (or anywhere else, really) background. See the following document from Intel, which gives a good explanation of the different access modes:

In short, it has extra data (a header) describing the data in each entry.

Moreover, I can't use ACCESS=stream due to machine being old and not supported, so I conclude that above is the only possibility to figure out the file structure. Any guidance would be a big help!

If you can't use stream, AFAIK there is really no simple and painless way to read binary files with no record information.

A possible solution which requires a C compiler is to do IO in a C function that you call from Fortran, "minimal" example:

main.f90:

program main integer, parameter :: dp = selected_real_kind(15) character(len=*), parameter :: filename = 'test.bin' real(dp) :: val call read_bin(filename, val) print*, 'Read: ', val end program 

read.c:

#include <string.h> #include <stdio.h> void read_bin_(const char *fname, double *ret, unsigned int len) { char buf[256]; printf("len = %d\n", len); strncpy(buf, fname, len); buf[len] = '\0'; // fortran strings are not 0-terminated FILE* fh = fopen(buf, "rb"); fread(ret, sizeof(double), 1, fh); fclose(fh); } 

Note that there is an extra parameter needed in the end and some string manipulation because of the way Fortran handles strings, which differs from C.

write.c:

#include <stdio.h> int main() { double d = 1.234; FILE* fh = fopen("test.bin", "wb"); fwrite(&d, sizeof(double), 1, fh); fclose(fh); } 

Compilation instructions:

gcc -o write write.c gcc -c -g read.c gfortran -g -o readbin main.f90 read.o 

Create binary file with ./write, then see how the Fortran code can read it back with ./readbin.

This can be extended for different data types to basically emulate access=stream. In the end, if you can recompile the original Fortran code to output the data file differently, this will be the easiest solution, as this one is pretty much a crude hack.

Lastly, a tip for getting into unknown data formats: The tool od is your friend, check its manpage. It can directly convert binary represantations into a variety of different native datatypes. Try with the above example (the z adds the character representation in the right-hand column, not very useful here, in general yes):

od -t fDz test.bin 
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks Markus, I am gonna try it next week. I just saw your response. On second note (addition to the question). During my search, I came across hexdump option (you mentioned od already). Would it make sense if I use hexdump conversion tools to read the file? Also I came across the possibility that MATLAB can read such files.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.