有什么高效的方法读取大型二进制文件的数据吗?

4 投票
6 回答
7780 浏览
提问于 2025-04-15 13:39

我需要处理一个二进制文件,里面的数据有好几十个GB。每条记录的长度都是不一样的。

所以这个文件看起来像这样:

<len1><data1><len2><data2>..........<lenN><dataN>

数据里包含整数、指针、双精度值等等。

我发现用Python处理这个情况有点困难。如果我把整个文件都读到内存里,那是没问题的,速度很快。但是,struct这个库在性能上表现得不太好,解压这些字节的时候几乎卡住了。

任何帮助都非常感谢。

谢谢。

6 个回答

2

看看 array 模块,特别是 array.fromfile 这个方法。这里有一句:

数据文件中的每条记录长度不固定。

这有点麻烦。不过你可以用一个 try-except 语句来处理这个问题。

2

如果你想在不把文件全部读入内存的情况下解析文件,可以使用bitstring这个模块。

这个模块内部其实是用到了struct模块和一个字节数组,但你可以用文件名来初始化一个不可变的Bits对象,这样就不会把整个文件都读到内存里。

举个例子:

from bitstring import Bits

s = Bits(filename='your_file')
while s.bytepos != s.length:
    # Read a byte and interpret as an unsigned integer
    length = s.read('uint:8')
    # Read 'length' bytes and convert to a Python string
    data = s.read(length*8).bytes
    # Now do whatever you want with the data

当然,你可以根据自己的需求来解析数据。

你也可以使用切片的方式来读取文件内容,不过要注意,切片的索引是以比特为单位,而不是字节。所以比如说s[-800:]实际上是最后100个字节。

5

struct(结构体)和 array(数组)是其他回答推荐的方案,这些方法在实现细节上是不错的,如果你的需求只是顺序读取整个文件或文件的一部分,这些可能就足够了。还有其他选择,比如 buffer(缓冲区)、mmap(内存映射),甚至 ctypes,具体取决于你没有提到的很多细节。如果没有合适且易用的库(比如 C、C++、Fortran 等)可以用来处理这个巨大的文件,或许一个稍微专业的 Cython 编写的助手可以提供你所需的额外性能。

但这里显然有一些特殊的问题——比如,一个数据文件怎么能包含指针呢?指针本质上是与内存地址相关的概念。它们可能是“偏移量”吗?如果是的话,那它们到底是如何定义和编码的?你的需求是否比简单的顺序读取更复杂(例如,随机访问)?如果是这样,你能否先进行一次“索引”处理,把从文件开始到记录开始的所有偏移量提取到一个更易用、格式更紧凑的辅助文件中?(那个偏移量的二进制文件非常适合用 array 来处理——除非这些偏移量需要的长度超过了你机器上 array 所支持的范围!)记录的长度和组成、记录的数量是如何分布的,才能组成“数十GB”的数据?等等等等。

你面临的是一个非常大规模的问题(而且无疑需要非常强大的硬件来支持,因为你提到可以轻松将整个文件读入内存,这意味着你有一台64位的机器,内存有几十GB——哇!),所以在处理这些问题时,仔细优化是非常值得的——但如果我们不知道足够的细节,就很难提供具体的帮助!-)

撰写回答