Search code examples
rfortranbinaryfiles

How to write .bin file in R and open it in Fortran


I have a Fortran model that I would like to force with data coming from a model developed in R, but I have trouble transferring the data between the two environments. I was thinking about using a .bin file.

What I am doing in R is using writeBin to store a multi-dim array in a .bin file:

a = seq(1,150,1)
my.array <- array(a, dim=c(10,5,3)) 

zz <- file("test.bin", "wb")
writeBin (as.vector(my.array),zz)
close(zz)

I can read the .bin file in R without problem again...

zz <- file("test.bin", "rb")
a1 = readBin(zz,"numeric", n=150)
close(zz)

my.array1 <- array(a1, dim=c(10,5,3)) 
my.array1

However when I try to open it in Fortran using the following code, the format is not recognized correctly.

PROGRAM playground
implicit none

! Type declarations
real, dimension (5,10,3) ::  a

! read binary
open(unit = 10, status='old',file='test.bin', form='formatted', action='read')  
read(10,"(f11.3)") a 

print*,a

END PROGRAM playground
PROGRAM playground

I assume I am using the wrong format in the read command, but not sure where I am going wrong as Fortran is new to me. Any suggestions?


Solution

  • You are trying to open the file as form='formatted'.

    Formatted means human readable, that is, a text file.

    You definitely need form='unformatted'. But the default would be access='sequential' which is not good for you, see https://stackoverflow.com/a/11570277/721644

    You should use access='stream' (or more complicated access='direct').

    The code from the linked answer can be adapted very easily to your problem. Just declare the array as:

    real(rp), dimension (5,10,3) ::  a
    

    and you must test which value of rp is the right one. I think the default real you tried is wrong and you need

    use, intrinsic :: iso_c_binding
    
    integer, parameter :: rp = c_double
    

    to use the C double precision real.

    Then just

    open(unit = 10, status='old',file='test.bin', form='unformatted', &
         access='stream', action='read')  
    read(10) a