在Python中,我如何在二进制文件中读取并循环该文件的每个字节?
当前回答
对于大尺寸,我认为使用生成器不会不好,这个答案是为了读取像文件这样的东西,虽然@codeapp有一个类似的答案,我认为删除内部循环会更有意义。
def read_chunk(file_object, chunk_size=125):
while True:
file = file_object.read(chunk_size)
if not file:
break
yield file
#sample use
buffer = io.BytesIO()
file = open('myfile', 'r')
for chunk in read_chunk(file):
buffer.write(chunk)
buffer.seek(0)
// save the file or do whatever you want here
你仍然可以使用它作为一个正常的列表,我不认为这是任何用途,但是
file_list = list(read_chunk(file, chunk_size=10000))
for i in file_list:
# do something
然后得到每个数据块的索引
for index, chunk in enumurate(read_chunk(file, chunk_size=10000)):
#use the index as a number index
# you can try and get the size of each chunk with this
length = len(chunk)
注意,要注意文件的大小,chunk_size总是以字节为单位。
其他回答
总结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)
在尝试了以上所有方法并使用@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')
参考
比目前任何方法都要快。希望它能帮助到一些人!
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()
Python 3,一次读取所有文件:
with open("filename", "rb") as binary_file:
# Read the whole file at once
data = binary_file.read()
print(data)
你可以使用data变量迭代任何你想要的东西。
如果要读取大量二进制数据,可能需要考虑struct模块。它被记录为“在C和Python类型之间”转换,但当然,字节就是字节,它们是否被创建为C类型并不重要。例如,如果你的二进制数据包含两个2字节整数和一个4字节整数,你可以这样读取它们(例子来自struct文档):
>>> struct.unpack('hhl', b'\x00\x01\x00\x02\x00\x00\x00\x03')
(1, 2, 3)
您可能会发现这比显式遍历文件内容更方便、更快,或者两者兼而有之。