用 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 无格式文件的主要内容,如果未能解决你的问题,请参考以下文章
C、C++ 或 Fortran 的代码抛光器/重新格式化器 [关闭]