用python读取二进制文件

用python读取二进制文件,python,binary,fortran,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 nu

我发现用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程序,读取这个二进制文件,然后保存我需要使用的数据?

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

请注意,如果字段之间/周围有“不可见”的填充,则需要找出原因并将其包含在
unpack()
调用中,否则将读取错误的位

读取文件内容以便解包非常简单:

import struct

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

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

这将解压前两个字段,假设它们从文件的最开始(无填充或无关数据)开始,并假设本机字节顺序(
@
符号)。格式化字符串中的
I
s表示“无符号整数,32位”。

您可以使用它,它可以从文本和二进制文件中读取数据。首先使用构造一个表示文件格式的数据类型,然后使用
numpy从文件中读取此类型。fromfile
读取二进制文件内容,如下所示:

with open(fileName, mode='rb') as file: # b is important -> binary
    fileContent = file.read()
{
    '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
}
然后使用以下方法“解包”二进制数据:

开始字节:
struct.unpack(“iiiii”,fileContent[:20])

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

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

结束字节:
struct.unpack(“i”,fileContent[-4:])
要将二进制文件读取到
字节
对象,请执行以下操作:

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)
import struct
ints = struct.unpack('iiii', data[:16])
要从数据中解压缩多个
int
s,请执行以下操作:

i = int.from_bytes(data[:4], byteorder='little', signed=False)
import struct
ints = struct.unpack('iiii', data[:16])

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

你会做这样的事情(我猜,因为我不懂Fortran):

产生如下输出:

with open(fileName, mode='rb') as file: # b is important -> binary
    fileContent = file.read()
{
    '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记录。如果您这样做,将欢迎拉取请求。

此文件是由Fortran程序编写的吗?如果是这样,它是如何写的,因为Fortran在默认情况下会在写入文件的每条记录之前添加额外的数据。在读取数据时,您可能需要注意这一点。请忽略我之前的评论,整数8和4*N显然是这一附加数据。另外,请参阅问题的答案。Numpy的
fromfile
函数可以轻松读取二进制文件。我建议您使用……并且始终注意您的endian nesses,尤其是在不同制造商的计算机之间进行移植时。好的,但我甚至不知道如何读取文件的字节。根据我的问题,我如何从字节5到8读取文件,然后将结果转换为整数?对不起,我是Python新手。关闭文件怎么样?打开文件是一种非常糟糕的做法,使用
with
语句可以很容易地避免这种情况。答案是有用的,但对于像我这样仍在学习如何使用PythonCan处理文件的人来说,它可能会产生误导。请看另一篇文章。。。我再次读取另一个二进制文件,但在本例中,我不知道字节结构的细节。例如,我发现有时有整数8。然而,使用IDL读取这些数据非常简单。我可以用python做同样的事情吗?请指出(在另一篇文章中,而不是在这里)为什么你对发布的答案和评论不满意。也许你也应该更新问题以提供更多细节。。。更新后我会看一看。如果需要将未打包的char[]转换为字符串,请参阅答案。
import struct
很容易错过这个!文档有点薄;请参阅以获取一些讨论,可能值得一点解释为什么这比其他答案更好(或至少与其他答案一样好)。您是否测试过一个验证过的测试,该测试使用fortran生成的二进制代码工作?并解释它的功能。。。什么是泡菜?pickle.load是什么?它加载Fortran流、直接文件还是顺序文件?它们不同且不兼容。Pickle二进制文件包含有关数据的信息。你可以自己测试一下。