在Python中,我如何在二进制文件中读取并循环该文件的每个字节?


当前回答

如果你正在寻找一些快速的方法,这里有一个我一直在使用的方法,它已经工作了很多年:

from array import array

with open( path, 'rb' ) as file:
    data = array( 'B', file.read() ) # buffer the file

# evaluate it's data
for byte in data:
    v = byte # int value
    c = chr(byte)

如果你想迭代字符而不是整数,你可以简单地使用data = file.read(),它应该是py3中的bytes()对象。

其他回答

Python >= 3.8

多亏了walrus操作符(:=),解决方案非常短。我们从文件中读取bytes对象,并将它们赋值给变量byte

with open("myfile", "rb") as f:
    while (byte := f.read(1)):
        # Do stuff with byte.

Python >= 3

在较旧的Python 3版本中,我们必须使用更详细的方式:

with open("myfile", "rb") as f:
    byte = f.read(1)
    while byte != b"":
        # Do stuff with byte.
        byte = f.read(1)

或者像benhoyt说的,跳过不相等,利用b""的值为假的事实。这使得代码在2.6和3之间兼容。X没有任何变化。如果从字节模式转换为文本模式或相反模式,也可以避免更改条件。

with open("myfile", "rb") as f:
    byte = f.read(1)
    while byte:
        # Do stuff with byte.
        byte = f.read(1)

Python >= 2.5

在Python 2中,这有点不同。这里我们得到的不是bytes对象,而是原始字符:

with open("myfile", "rb") as f:
    byte = f.read(1)
    while byte != "":
        # Do stuff with byte.
        byte = f.read(1)

注意,with语句在Python 2.5以下版本中不可用。要在v 2.5中使用它,你需要导入它:

from __future__ import with_statement

在2.6中不需要这样做。

Python 2.4及更早版本

f = open("myfile", "rb")
try:
    byte = f.read(1)
    while byte != "":
        # Do stuff with byte.
        byte = f.read(1)
finally:
    f.close()

在尝试了以上所有方法并使用@Aaron Hall的答案后,我在一台运行windows 10, 8gb RAM和Python 3.5 32位的计算机上得到了一个~ 90mb的文件的内存错误。我的一位同事推荐我使用numpy,它的效果非常好。

到目前为止,读取整个二进制文件(我测试过)的最快速度是:

import numpy as np

file = "binary_file.bin"
data = np.fromfile(file, 'u1')

参考

比目前任何方法都要快。希望它能帮助到一些人!

下面是一个使用Numpy fromfile读取网络端数据的例子:

dtheader= np.dtype([('Start Name','b', (4,)),
                ('Message Type', np.int32, (1,)),
                ('Instance', np.int32, (1,)),
                ('NumItems', np.int32, (1,)),
                ('Length', np.int32, (1,)),
                ('ComplexArray', np.int32, (1,))])
dtheader=dtheader.newbyteorder('>')

headerinfo = np.fromfile(iqfile, dtype=dtheader, count=1)

print(raw['Start Name'])

我希望这能有所帮助。问题是fromfile不能识别和EOF,并允许对任意大小的文件优雅地跳出循环。

如果要读取大量二进制数据,可能需要考虑struct模块。它被记录为“在C和Python类型之间”转换,但当然,字节就是字节,它们是否被创建为C类型并不重要。例如,如果你的二进制数据包含两个2字节整数和一个4字节整数,你可以这样读取它们(例子来自struct文档):

>>> struct.unpack('hhl', b'\x00\x01\x00\x02\x00\x00\x00\x03')
(1, 2, 3)

您可能会发现这比显式遍历文件内容更方便、更快,或者两者兼而有之。

如果你正在寻找一些快速的方法,这里有一个我一直在使用的方法,它已经工作了很多年:

from array import array

with open( path, 'rb' ) as file:
    data = array( 'B', file.read() ) # buffer the file

# evaluate it's data
for byte in data:
    v = byte # int value
    c = chr(byte)

如果你想迭代字符而不是整数,你可以简单地使用data = file.read(),它应该是py3中的bytes()对象。