我必须在python中读取二进制文件。这首先是由Fortran 90程序以这种方式编写的:
open(unit=10,file=filename,form='unformatted')
write(10)table%n1,table%n2
write(10)table%nH
write(10)table%T2
write(10)table%cool
write(10)table%heat
write(10)table%cool_com
write(10)table%heat_com
write(10)table%metal
write(10)table%cool_prime
write(10)table%heat_prime
write(10)table%cool_com_prime
write(10)table%heat_com_prime
write(10)table%metal_prime
write(10)table%mu
if (if_species_abundances) write(10)table%n_spec
close(10)
我可以使用以下IDL代码轻松读取此二进制文件:
n1=161L
n2=101L
openr,1,file,/f77_unformatted
readu,1,n1,n2
print,n1,n2
spec=dblarr(n1,n2,6)
metal=dblarr(n1,n2)
cool=dblarr(n1,n2)
heat=dblarr(n1,n2)
metal_prime=dblarr(n1,n2)
cool_prime=dblarr(n1,n2)
heat_prime=dblarr(n1,n2)
mu =dblarr(n1,n2)
n =dblarr(n1)
T =dblarr(n2)
Teq =dblarr(n1)
readu,1,n
readu,1,T
readu,1,Teq
readu,1,cool
readu,1,heat
readu,1,metal
readu,1,cool_prime
readu,1,heat_prime
readu,1,metal_prime
readu,1,mu
readu,1,spec
print,spec
close,1
我想要做的是用Python读取这个二进制文件。但是有一些问题。 首先,这是我尝试阅读文件:
import numpy
from numpy import *
import struct
file='name_of_my_file'
with open(file,mode='rb') as lines:
c=lines.read()
我尝试阅读前两个变量:
dummy, n1, n2, dummy = struct.unpack('iiii',c[:16])
但是你可以看到我必须添加到虚拟变量,因为不知何故,fortran程序在这些位置添加整数8。
现在问题是在尝试读取其他字节时。我没有得到与IDL计划相同的结果。
这是我尝试读取数组n
double = 8
end = 16+n1*double
nH = struct.unpack('d'*n1,c[16:end])
然而,当我打印这个数组时,我得到了非感觉值。我的意思是,我可以用上面的IDL代码读取文件,所以我知道会发生什么。所以我的问题是:当我不确切知道结构时,我怎么能读到这个文件?为什么使用IDL它是如此简单易读?我需要用Python读取这个数据集。
答案 0 :(得分:5)
您正在寻找的是struct
模块。
此模块允许您从字符串中解压缩数据,将其视为二进制数据。
您提供格式字符串和文件字符串,它将使用返回二进制对象的数据。
例如,使用您的变量:
import struct
content = f.read() #I'm not sure why in a binary file you were using "readlines",
#but if this is too much data, you can supply a size to read()
n, T, Teq, cool = struct.unpack("dddd",content[:32])
这将使n,T,Teq和cool保存二进制文件中的前四个双精度数。当然,这只是一个示范。你的例子看起来像是想要双打的列表 - 方便的struct.unpack
返回一个元组,我为你的情况采取的仍然可以正常工作(如果不是,你可以让他们搞砸)。请记住,struct.unpack
需要使用传入其中的整个字符串 - 否则您将获得struct.error
。因此,要么对输入字符串进行切片,要么只使用read
您要使用的字符数,就像我在评论中所说的那样。
例如,
n_content = f.read(8*number_of_ns) #8, because doubles are 8 bytes
n = struct.unpack("d"*number_of_ns,n_content)
答案 1 :(得分:0)
答案 2 :(得分:0)
您好像正在尝试阅读RAMSES生成的 cooling_0000x.out 文件。
请注意,前两个整数(n1,n2)提供了文件正文中后面的二维表(数组)的维度...所以你需要先知道这两个整数才能知道多少真正的* 8数据在文件的其余部分。
scipy应该有帮助 - 它可以让你读取任意尺寸的二进制数据:
http://wiki.scipy.org/Cookbook/InputOutput#head-e35c7736718209eea00ebf37a7e1dfb91df696e1
如果你已经有这个python代码,请告诉我,因为我今天要写的(17Sep2014)。
瑞克