Search code examples
binaryfortranjulia

Reading a binary file with Julia


Hi im new in Julia and im trying to do some proprocessing with it. I have a lot of files in binary. Im using F90 for the processing. The file that i write are like this

open(11,file="ring.grid",form="unformatted")

write(11)nv
write(11)Nx,Ny,Nzt
write(11) xx
write(11) yy
write(11) zz
close(11)


where, nv,nx,ny,nzt are integers and xx,yy,zz are 3D matrix. In F90 i use this simple block to read the file

open(11,file='ring.grid',form='unformatted')
read(11)nd
read(11)n1,n2,n3
read(11)xx
read(11)yy
read(11)zz
close(11)

But i have troubles to read it with Julia. Someone can help me with this? Thank you

I tried using

io=read(NAMEFILE)
y=Array{UInt8,1}(undef,1)
read!(io,y)

But i dont know how i can separe the nv,n1,n2,n3,xx,yy,zz in differente arrays


Solution

  • Suppose that the complete F90 code to write the data looks like this:

    program SaveGrid
        implicit none
    
        integer :: nv
        integer :: Nx, Ny, Nzt
        real, dimension(:), allocatable :: xx, yy, zz
        integer :: i
    
        nv = 3
        Nx = 5
        Ny = 7
        Nzt = 10
    
        allocate(xx(Nx), yy(Ny), zz(Nzt))
    
        do i = 1, Nx
            xx(i) = float(i)
        end do
        do i = 1, Ny
            yy(i) = float(i) * 2.0
        end do
        do i = 1, Nzt
            zz(i) = float(i) * 3.0
        end do
    
        open(unit=11, file="ring.grid", form="unformatted")
    
        write(11) nv
        write(11) Nx, Ny, Nzt
        write(11) xx
        write(11) yy
        write(11) zz
    
        close(11)
    
        deallocate(xx, yy, zz)
    end program SaveGrid
    

    To read this into Julia you need to handle the way that F90 writes unformatted data.

    function read_fortran_binary(filename)
        open(filename, "r") do file
            # Read record marker.
            record_size = read(file, Int32)
            # Read data.
            nv = read(file, Int32)
            # Read record marker.
            end_record_size = read(file, Int32)
    
            # Read record marker.
            read(file, Int32)
            # Read data.
            Nx = read(file, Int32)
            Ny = read(file, Int32)
            Nzt = read(file, Int32)
            # Read record marker.
            read(file, Int32)
    
            return nv, Nx, Ny, Nzt
        end
    end
    
    nv, Nx, Ny, Nzt = read_fortran_binary("ring.grid")
    
    println("nv:  ", nv)
    println("Nx:  ", Nx)
    println("Ny:  ", Ny)
    println("Nzt: ", Nzt)
    

    There are record markers both before and after each chunk of data written to the file. You need to read these too. Obviously you don't need to ignore these data and the record sizes can be used to make your Julia code more robust and flexible by catering for changes in the unformatted F90 data.

    nv:  3
    Nx:  5
    Ny:  7
    Nzt: 10