用python读取二进制文件

时间:2012-01-03 09:57:52

标签: python binary fortran

我发现使用Python读取二进制文件特别困难。你能帮我个忙吗? 我需要阅读这个文件,它在Fortran 90中很容易被

读取
int*4 n_particles, n_groups
real*4 group_id(n_particles)
read (*) n_particles, n_groups
read (*) (group_id(j),j=1,n_particles)

详细说明,文件格式为:

Bytes 1-4 -- The integer 8.
Bytes 5-8 -- The number of particles, N.
Bytes 9-12 -- The number of groups.
Bytes 13-16 -- The integer 8.
Bytes 17-20 -- The integer 4*N.
Next many bytes -- The group ID numbers for all the particles.
Last 4 bytes -- The integer 4*N. 

我如何用Python阅读?我尝试了一切,但从未奏效。我有没有机会在python中使用f90程序,读取这个二进制文件,然后保存我需要使用的数据?

6 个答案:

答案 0 :(得分:106)

阅读二进制文件内容,如下所示:

with open(fileName, mode='rb') as file: # b is important -> binary
    fileContent = file.read()

然后使用struct.unpack“解压缩”二进制数据:

起始字节:struct.unpack("iiiii", fileContent[:20])

正文:忽略标题字节和尾随字节(= 24);剩下的部分形成了主体,要知道正文中的字节数做整数除以4;获得的商乘以字符串'i',以便为解包方法创建正确的格式:

struct.unpack("i" * ((len(fileContent) -24) // 4), fileContent[20:-4])

结束字节:struct.unpack("i", fileContent[-4:])

答案 1 :(得分:22)

一般情况下,我建议您考虑使用Python的struct模块。它是Python的标准,将问题的规范转换为适合struct.unpack()的格式字符串应该很容易。

请注意,如果有""隐形"在字段之间/周围填充,您需要弄清楚并将其包含在unpack()调用中,否则您将读取错误的位。

读取文件的内容以便解压缩是非常简单的:

import struct

data = open("from_fortran.bin", "rb").read()

(eight, N) = struct.unpack("@II", data)

这会解压缩前两个字段,假设它们从文件的最开头开始(没有填充或无关数据),并且还假设是本机字节顺序(@符号)。格式化字符串中的I表示"无符号整数,32位"。

答案 2 :(得分:11)

您可以使用numpy.fromfile,它可以读取文本和二进制文件中的数据。您将首先使用numpy.dtype构建表示文件格式的数据类型,然后使用numpy.fromfile从文件中读取此类型。

答案 3 :(得分:1)

要将二进制文件读取到bytes对象中:

from pathlib import Path
data = Path('/path/to/file').read_bytes()  # Python 3.5+

要从数据的字节0-3创建int

i = int.from_bytes(data[:4], byteorder='little', signed=False)

要从数据中解压缩多个int

import struct
ints = struct.unpack('iiii', data[:16])

答案 4 :(得分:0)

我也发现在读取和写入二进制文件方面缺少Python,因此我编写了一个小模块(适用于Python 3.6 +)。

使用binaryfile,您会做类似的事情(我猜是因为我不了解Fortran):

import binaryfile

def particle_file(f):
    f.array('group_ids')  # Declare group_ids to be an array (so we can use it in a loop)
    f.skip(4)  # Bytes 1-4
    num_particles = f.count('num_particles', 'group_ids', 4)  # Bytes 5-8
    f.int('num_groups', 4)  # Bytes 9-12
    f.skip(8)  # Bytes 13-20
    for i in range(num_particles):
        f.struct('group_ids', '>f')  # 4 bytes x num_particles
    f.skip(4)

with open('myfile.bin', 'rb') as fh:
    result = binaryfile.read(fh, particle_file)
print(result)

哪个会产生这样的输出:

{
    'group_ids': [(1.0,), (0.0,), (2.0,), (0.0,), (1.0,)],
    '__skipped': [b'\x00\x00\x00\x08', b'\x00\x00\x00\x08\x00\x00\x00\x14', b'\x00\x00\x00\x14'],
    'num_particles': 5,
    'num_groups': 3
}

我使用skip()跳过了Fortran添加的其他数据,但是您可能想添加一个实用程序来正确处理Fortran记录。如果这样做,将欢迎请求请求。

答案 5 :(得分:-1)

res.end()