How do I read a FORTRAN unformatted binary data file into MATLAB?

136 views (last 30 days)
Below is a data file generated by a FORTRAN program. The following is the hexadecimal dump of the FORTRAN binary data file:
0000000 0000 0048 4920 616d 2061 2067 656e 6975
0000020 7320 6772 6f75 6e64 686f 6721 2020 5275
0000040 6e21 2020 5275 6e21 2020 5275 6e21 2020
0000060 2020 2020 2020 2020 2020 2020 2020 2020
0000100 2020 2020 2020 2020 2020 2020 0000 0048
0000120 0000 000c 3f8c cccd 400c cccd 4053 3333
0000140 0000 000c 0000 0008 0000 0004 0000 0005
0000160 0000 0008
A similar data file from C (flat binary file) is attached to this solution. Below is the code that was used to generate the binary data file.
program wrt_bin
character*72 name
real*4 xsource, zsource, dt
integer*4 ntrace, nt
name='I am a genius groundhog! Run! Run! Run!'
xsource=1.1
zsource=2.2
dt=3.3
ntrace=4
nt=5
open(unit=11, file='wrt_bin.bin', form='unformatted',
+ status='new')
WRITE(11) NAME
WRITE(11) XSOURCE,ZSOURCE,DT
WRITE(11) NTRACE,NT
close(11)
end
Here is the C code that was used to generate the flat binary data file:
#include<stdio.h>
#include<stdlib.h>
void main()
{
char name[72];
int ntrace, nt;
double xsource, zsource, dt;
FILE *fp;
sprintf(name," I am a genius groundhog! Run! Run! Run!");
xsource=1.1;
zsource=2.2;
dt=3.3;
ntrace=4;
nt=5;
fp=fopen("wrt_binc.bin", "wb");
fwrite(name, sizeof(char), 72, fp);
fwrite(&xsource, sizeof(double), 1, fp);
fwrite(&zsource, sizeof(double), 1, fp);
fwrite(&dt, sizeof(double), 1, fp);
fwrite(&ntrace, sizeof(int), 1, fp);
fwrite(&nt, sizeof(int), 1, fp);
fclose(fp);
}

Accepted Answer

MathWorks Support Team
MathWorks Support Team on 25 Mar 2018
Binary files that are generated by FORTRAN are quite different than ones that are expected by MATLAB. MATLAB expects a flat binary file. FORTRAN binary files are not flat.
UNIX: An unformatted FORTRAN binary file contains record length information along with each record. A record is a WRITE statement. Thus, the code above has 3 records. The record length information is tagged on at the beginning and end of each record. At the beginning of the FORTRAN binary data file is the record length "0000 0048". This is the record length in hex, i.e. 72 bytes. Counting 72 bytes from that point is another "0000 0048" which is followed by "0000 000c" (this is the length of the next record, i.e. 12 bytes or 3 times 4 bytes). The extraneous characters must either be filtered out or stripped off. The easiest thing to do would be to filter them out when you are reading the data into MATLAB. Stripping them off would require writing C code.
Here is the sequence of MATLAB commands that illustrates what you need to do:
fid=fopen('wrt_bin.bin', 'rb'); % Open the file.
hr1=fread(fid, 1, 'int32') % Read the first record start tag. Returns hr1 = 72
name=setstr(fread(fid, 72, 'uchar'))' % Read the first record. Returns name = I am a genius % groundhog! Run! Run! Run!
hr1=fread(fid, 1, 'int32') % Read the first record end tag. Returns hr1 = 72
hr2=fread(fid, 1, 'int32') % Read the second record start tag. Returns hr2 = 12
xsource=fread(fid, 1, 'float32') % Read data. Returns xsource = 1.1000
zsource=fread(fid, 1, 'float32') % Read data. Returns zsource = 2.2000
dt=fread(fid, 1, 'float32') % Read data. Returns dt = 3.3000
hr2=fread(fid, 1, 'int32') % Read the second record end tag. Returns hr2 = 12
hr3=fread(fid, 1, 'int32') % Read the third record start tag. Returns hr3 = 8
ntrace=fread(fid, 1, 'int32') % Read data. Returns ntrace = 4
nt=fread(fid, 1, 'int32') % Read data. Returns nt = 5
hr3=fread(fid, 1, 'int32') % Read the third record end tag. Returns hr3 = 8
fclose(fid); % Close file.
You will have to modify your MATLAb file to read out the record length information and access the data in which you are interested. An alternative would be to use the FSEEK() command in MATLAB to jump over the record length information and access the data directly. Here is an example file that does so:
fid=fopen('wrt_bin.bin', 'rb');
fseek(fid, 4, 'cof');
name=setstr(fread(fid, 72, 'uchar'))';
fseek(fid, 4, 'cof');
fseek(fid, 4, 'cof');
xsource=fread(fid, 1, 'float32');
zsource=fread(fid, 1, 'float32');
dt=fread(fid, 1, 'float32');
fseek(fid, 4, 'cof');
fseek(fid, 4, 'cof');
ntrace=fread(fid, 1, 'int32');
nt=fread(fid, 1, 'int32');
fclose(fid);
xsource, zsource, dt, ntrace, nt
Here is the output:
xsource = 1.1000 zsource = 2.2000 dt = 3.3000 ntrace = 4 nt = 5
To apply the MATLAB code to a binary file created with Digital Visual Fortran and Windows requires a few modifications. Since Digitial Fortran writes two unsigned characters as the start tag and has no end tag, you need code such as that below in order to read a binary file produced by Digital Fortran code:
tag=setstr(fread(fid,2,'uchar')); %read the first record start tag
capf=fread(fid,1,'float'); %capture fraction
rot=fread(fid,1,'float'); %grid rotation, radians
tag=setstr(fread(fid,2,'uchar')); %read the second record start tag
nx=fread(fid,1,'int'); %number cells alongwind
xgrid=fread(fid,nx,'float'); %alongwind grid points, m
tag=setstr(fread(fid,2,'uchar')); %read the third record start tag
ny=fread(fid,1,'int'); %number cells crosswind
ygrid=fread(fid,ny,'float'); %crosswind grid points, m
tag=setstr(fread(fid,2,'uchar')); %read the fourth record start tag
dose=fread(fid,nx*ny,'float32'); %read the dose matrix
tag=setstr(fread(fid,2,'uchar')); %read the fifth record start tag
dep=fread(fid,nx*ny,'float32'); %read the deposition matrix
NOTE: The Digital Visual Fortran information was submitted by one of our customers and has not been verified by MathWorks.

More Answers (0)

Products

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!