在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()对象。

其他回答

这个生成器从文件中产生字节,以块的形式读取文件:

def bytes_from_file(filename, chunksize=8192):
    with open(filename, "rb") as f:
        while True:
            chunk = f.read(chunksize)
            if chunk:
                for b in chunk:
                    yield b
            else:
                break

# example:
for b in bytes_from_file('filename'):
    do_stuff_with(b)

有关迭代器和生成器的信息,请参阅Python文档。

总结chrispy, Skurmedel, Ben Hoyt和Peter Hansen的所有出色之处,这将是一次一个字节处理二进制文件的最佳解决方案:

with open("myfile", "rb") as f:
    while True:
        byte = f.read(1)
        if not byte:
            break
        do_stuff_with(ord(byte))

对于python 2.6及以上版本,因为:

Python内部缓冲区-不需要读取块 DRY原则——不重复读行 语句确保干净的文件关闭 当没有更多字节时,'byte'的计算结果为false(当字节为零时不是)

或使用J. F.塞巴斯蒂安的解决方案提高速度

from functools import partial

with open(filename, 'rb') as file:
    for byte in iter(partial(file.read, 1), b''):
        # Do stuff with byte

或者如果你想把它作为一个生成器函数,就像codeape演示的那样:

def bytes_from_file(filename):
    with open(filename, "rb") as f:
        while True:
            byte = f.read(1)
            if not byte:
                break
            yield(ord(byte))

# example:
for b in bytes_from_file('filename'):
    do_stuff_with(b)

Python 3,一次读取所有文件:

with open("filename", "rb") as binary_file:
    # Read the whole file at once
    data = binary_file.read()
    print(data)

你可以使用data变量迭代任何你想要的东西。

下面是一个使用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)

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