用 Python 编写 Fortran 无格式文件

Posted

技术标签:

【中文标题】用 Python 编写 Fortran 无格式文件【英文标题】:Writing Fortran unformatted files with Python 【发布时间】:2013-02-05 18:38:14 【问题描述】:

我有一些由 Fortran77 编写的单精度 little-endian 无格式数据文件。我正在使用 Python 使用以下命令读取这些文件:

import numpy as np
original_data = np.dtype('float32')
f = open(file_name,'rb')                                                                                                 
original_data = np.fromfile(f,dtype='float32',count=-1)                                                                            
f.close()

在 Python 中进行一些数据操作后,我(正在尝试)使用 Python 使用以下命令将它们写回原始格式:

out_file = open(output_file,"wb")                                                                                             
s = struct.pack('f'*len(manipulated_data), *manipulated_data)                                                                     
out_file.write(s)
out_file.close()

但它似乎不起作用。任何想法使用 Python 以原始 fortran 未格式化格式写回数据的正确方法是什么?

问题详情:

我能够使用来自 Fortran 的操作数据读取最终文件。但是,我想使用软件(Paraview)可视化这些数据。为此,我将未格式化的数据文件转换为 *h5 格式。我能够使用 h5 实用程序将原始数据和操作数据转换为 h5 格式。但是,虽然 Paraview 能够读取从原始数据创建的 *h5 文件,但 Paraview 无法读取从操纵数据创建的 *h5 文件。我猜有些东西在翻译中丢失了。

这就是我在 Fortran 中打开 Python 编写的文件的方式(单精度数据):

open (in_file_id,FILE=in_file,form='unformatted',access='direct',recl=4*n*n*n)

这是我正在用 Fortran 编写的原始未格式化数据:

open(out_file_id,FILE=out_file,form="unformatted")

这些信息是否足够?

【问题讨论】:

也许这有帮助:scipy.org/Cookbook/FortranIO 为什么不直接从 Fortran 将其保存到 hdf5 或 vtk? 另请参阅这个 SO 问题:Fortran unformatted file format id 做的第一件事(除了不使用未格式化的 fortran 之外)是在不进行任何数据操作的情况下完成整个过程。您最终应该得到完全相同的文件,否则您可以找出不同之处。 进一步查看您的输入代码未正确读取未格式化的 fortran(您的字面意思是用 form=unformatted 对吗?)。未格式化文件中的第一个字段应该是 int32。您的代码为第一个数组元素提供垃圾,然后是数据。 【参考方案1】:

您是否尝试过使用操作数据数组的 .tofile 方法?它将按 C 顺序写入数组,但能够写入纯二进制。

.tofile 的文档也表明这与以下内容相同:

with open(outfile, 'wb') as fout:
    fout.write(manipulated_data.tostring())

【讨论】:

【参考方案2】:

这是创建一个未格式化的顺序访问文件:

open(out_file_id,FILE=out_file,form="unformatted")

假设您正在编写单个数组real a(n,n,n),仅使用write(out_file_id)a,您应该会看到文件大小为 4*n^3+8 字节。额外的 8 个字节是一个 4 字节整数 (=4n^3),在记录的开头和结尾重复。

第二种形式:

open (in_file_id,FILE=in_file,form='unformatted',access='direct',recl=4*n*n*n)

打开没有这些标题的直接访问。对于现在写作,您将拥有write(unit,rec=1)a。如果您使用 direct 访问读取您的 sequential 访问文件,它将正确读取,但您会将该整数标头读取为浮点数(垃圾),如 (1,1 ,1) 数组值,然后其他所有内容都被移动。您说您可以使用 fortran 进行阅读,但您是否希望看到您真的在阅读您所期望的内容?

解决此问题的最佳方法是将原始 fortran 代码修复为使用未格式化的直接访问进行读写。这为您提供了一个“普通”的原始二进制文件,没有标题。

在您的 python 中,您需要先读取该 4 字节整数,然后再读取您的数据。在输出时,您可以根据 paraview 过滤器的预期将整数标头放回或不放。

--------- 这里是 python 读取/修改/写入包含单个记录的无格式顺序 fortran 文件:

import struct
import numpy as np
f=open('infile','rb')
recl=struct.unpack('i',f.read(4))[0]
numval=recl/np.dtype('float32').itemsize
data=np.fromfile(f,dtype='float32',count=numval)
endrec=struct.unpack('i',f.read(4))[0]
if endrec is not recl: print "error unexpected end rec"
f.close()
f=open('outfile') 
f.write(struct.pack('i',recl))
for i in range(0,len(data)):data[i] = data[i]**2  #example data modification
data.tofile(f)
f.write(struct.pack('i',recl)

只循环多条记录。请注意,这里的数据是作为向量读取的,并且假定都是浮点数。当然,您需要知道实际的数据类型才能使用它.. 另请注意,您可能需要根据平台处理字节顺序问题。

【讨论】:

感谢乔治的详细解释!

以上是关于用 Python 编写 Fortran 无格式文件的主要内容,如果未能解决你的问题,请参考以下文章

Fortran 未格式化文件中的意外“填充”

C、C++ 或 Fortran 的代码抛光器/重新格式化器 [关闭]

HDF5 用于使用 fortran 编写的数据文件

Visual Studio2008即时自动检查语法错误;用于编写Fortran程序。

Qt图形界面程序如何调用fortran编写的控制台程序?

Fortran中生成的.dat文件,怎么用tecplot打开?