AstroInt
AstroInt

Reputation: 63

Writing binary access stream data in Python2 for reading in Fortran

I don't have working knowledge of Fortran, nor am I an advanced user of Python(2), so please bear that in mind and please be understanding!

I'm trying to write some data into a binary file with Python2 (opened an empty binary file with "wb"), which has to be opened as an "unformatted" file in Fortran (a .f90 file). The thing is, such a Python-generated binary file can be read (in Fortran) if I have, when opening the file in Fortran,

"form='unformatted'", and "access='stream'".

I am hoping to write a binary file in Python 2 such that I do not need "access='stream'". I am using this binary file in conjunction with a massive nonpublic code in Fortran (which I did not develop), and would like to not touch the source code at all. I only made changes as a test for myself.

If I do not use "access='stream'", then I just get nonsensical values that are output.

I was using the below before (byteswap() for changing endianness) to write the binary file, to no avail.

dxidxup = 1/dxm
dxidxup = np.array(dxidxup,dtype='<f4')
dxidxup_write = dxidxup.byteswap()
dxidxup_write.tofile(new_mesh)

I also tried to use np.ascontiguousarray and np.asfortranarray to write the data to the binary file, but it did not work either.

dxidxup = 1/dxm
dxidxup = np.array(dxidxup)
dxidxup = np.ascontiguousarray(dxidxup,dtype='<f4')
dxidxup_write = dxidxup.byteswap()
dxidxup_write.tofile(new_mesh)

I have tried struct.pack too, as per this link. I am not sure what other avenue to best pursue... I appreciate thoughts/inputs!

I hope that all made sense..

Upvotes: 0

Views: 228

Answers (1)

MauiMuc
MauiMuc

Reputation: 50

Well, this may be quite tricky. Binary input/output particularly depends on the chosen Fortran compiler and limits portability.

In case of UNFORMATED SEQUENTIAL or DIREC input/output Fortran causes logical records to be read or written. Fortran inserts an integer byte count at the beginning and end of data written.

Here is an example with two records of length two and three that works with fort77. Python code for generating the binary:

import struct
fh = open('two_records.bin', 'wb')
fh.write(struct.pack('l',2)) # Compiler dependent
fh.write('ab')
fh.write(struct.pack('l',2))
fh.write(struct.pack('l',3))
fh.write('cde')
fh.write(struct.pack('l',3))
fh.close()

Fortran 77 Code that reads the file:

      character*2 a
      character*3 b
      open(12, FILE='two_records.bin', FORM='unformatted')
      read(12) a
      read(12) b
      close(12)
      end

If you prefer any other compiler you have to figure out if the byte count is int or longint. In contrast to f2c, by default gfortran uses int32 which may be changed by setting -frecord-marker=8.

Upvotes: 0

Related Questions