在python中读取二进制文件

2024-04-27 12:16:49 发布

您现在位置:Python中文网/ 问答频道 /正文

我必须用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读取这个数据集。


Tags: 文件com二进制primefilewriteidlspec
3条回答

你要找的是^{}模块。

此模块允许您从字符串中解压数据,将其视为二进制数据。

提供格式字符串和文件字符串,它将使用返回二进制对象的数据。

例如,使用变量:

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保持二进制文件中的前四个双精度数。当然,这只是一个示范。你的例子看起来需要double列表-方便地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)

看起来您正试图读取RAMSES生成的cooling x.out文件。

注意,前两个整数(n1,n2)提供了文件主体中后面的二维表(数组)的维度。。。所以你需要先处理这两个整数,然后才能知道文件其余部分中有多少真正的*8数据。

scipy应该有帮助——它允许您读取任意维度的二进制数据:

http://wiki.scipy.org/Cookbook/InputOutput#head-e35c7736718209eea00ebf37a7e1dfb91df696e1

如果您已经有了这个python代码,请让我知道,因为我今天(2014年9月17日)将要编写它。

瑞克

你试过scipy.io.readsav吗?

只需阅读如下文件:

mydict = scipy.io.readsav('name_of_file')

相关问题 更多 >