如何使用Python读取Fortran创建的整个二进制文件

时间:2018-08-01 03:37:21

标签: python scipy fortran

我使用Fortran创建一个包含多行的二进制文件:

Program write_binary
implicit none
integer i
real x
open(10,file="test.dat",form="unformatted")
do i=1,10
   write(10),i*1.0,i*2.0
end do
close(10)
end

然后我使用Python,尝试读取整个文件。但是,FortranFile包只能逐行读取(请参见下面的代码)。有什么办法可以读取Fortran创建的二进制文件的所有行?非常感谢。

from scipy.io import FortranFile
import numpy as np
f=FortranFile('test.dat','r')
x=read_reals(dtype='f4')
print(x)

1 个答案:

答案 0 :(得分:1)

我经常用Fortran编写数据并用Python读取数据。我将在这里针对多个3D阵列的情况进行解释,因为它更通用并且更容易适应1D阵列。

在Fortran中,我使用以下循环编写数据:

file = 'my_fortran_data.dat'
open(99, file=file, status = 'replace', action = 'write', form = 'unformatted', access='stream')
    do k = 1,L
        do j = 1,M
            do i = 1,N
                write(99) u(i,j,k), v(i,j,k), w(i,j,k)
            end do
        end do
    end do
close(99)

请注意,我将数据写入stream访问中。因此,我不会记录每个记录的开头和结尾(使文件变小)。

我从Python使用以下函数读取以下数据:

def read_data(file, dtype, stream):
    """
    Return the components of a 3D vector field stored in binary format.
    The data field is supposed to have been written as: (for k; for j; for i;) where the last dimension
    is the quickest varying index. Each record should have been written as: u, v, w.
    The returned components are always converted in np.double precision type.

    Args:
        dim: number of dimensions
        dtype: numpy dtype object. Single or double precision expected.
        stream: type of access of the binary output. If true, the file can only contain data. 
    If false, there is a 4-byte header and footer around each "record"
            in the binary file (can happen in some Fortran compilers if access != 'stream').
    """
    if stream:
        shape = (L, M, N, 3)
        f = open(file, 'rb')
        data = np.fromfile(file=f, dtype=dtype).reshape(shape)
        f.close()
        u = data[:, :, :, 0].transpose(2, 1, 0)
        v = data[:, :, :, 1].transpose(2, 1, 0)
        w = data[:, :, :, 2].transpose(2, 1, 0)
        del data

    else:
        shape = (L, M, N, 5)
        f = open(file, 'rb')
        data = np.fromfile(file=f, dtype=dtype).reshape(shape)
        f.close()
        u = data[:, :, :, 1].transpose(2, 1, 0)
        v = data[:, :, :, 2].transpose(2, 1, 0)
        w = data[:, :, :, 3].transpose(2, 1, 0)
        del data

    u = u.astype(np.float64, copy=False)
    v = v.astype(np.float64, copy=False)
    w = w.astype(np.float64, copy=False)
    return(u, v, w)

请注意,我总是将数据转换为双精度,但是如果不需要,您可以省略最后一步。

根据您的情况,对shape=(10,2)访问使用stream,否则使用shape=(10,4)