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

3

我使用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)

4
Fortran非格式化文件中没有行,只有记录。而且是的,FortranFile一次只能读取一个记录。请使用循环。 - Amadan
1个回答

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)

请注意,我使用流式访问方式编写我的数据。因此,我不记录每个记录的开头和结尾(从而使文件大小更小)。
从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)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接