【问题标题】:reading a binary file in python在python中读取二进制文件
【发布时间】:2011-12-26 21:46:40
【问题描述】:

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

【问题讨论】:

  • 向我们展示文件中的前两行或三行。此外,您在顶部设置的变量与从文件中读取n 没有太大关系...
  • 但是我的文件是二进制文件。这就是为什么我向您展示了在 IDL 中读取它的代码...最后我想读取我声明的所有变量,而不仅仅是 n
  • 快速谷歌搜索显示“IDLSave - 用于读取 IDL 'save' 文件的 python 模块”astrofrog.github.com/idlsave
  • “当我不知道确切的结构时如何读取这个文件”:哪个部分未知?四个整数不总是在那里吗?数据不总是翻倍吗?
  • @georg“保存”文件与“.bil”文件相同吗?

标签: python idl-programming-language


【解决方案1】:

您正在寻找的是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)

【讨论】:

    【解决方案2】:

    您尝试过scipy.io.readsav 吗?

    只需像这样读取文件:

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

    【讨论】:

    • 好的,然后忘记这个答案。我建议您更新您的帖子,以澄清您谈论的是二进制文件,而不是保存文件,并且您不能使用评论中引用的模块 IDL 保存。
    【解决方案3】:

    您似乎正在尝试读取 RAMSES 生成的 cooling_0000x.out 文件。

    请注意,前两个整数 (n1, n2) 提供了文件正文中的两个维度表(数组)的维度...所以您需要先处理这两个整数才能知道多少real*8 数据在文件的其余部分。

    scipy 应该会有所帮助——它可以让您读取任意维度的二进制数据:

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

    如果你已经有了这个 python 代码,请告诉我,因为我今天(2014 年 9 月 17 日)要写它。

    瑞克

    【讨论】:

    • scipy.io.FortranFile() 允许您读入 fortran 未格式化的文件。 (另外,RAMSES 提供了一个fortranfile.py 文件)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-01
    • 1970-01-01
    • 2017-11-27
    • 1970-01-01
    • 2019-02-20
    相关资源
    最近更新 更多