python读二进制文件遍历_读取二进制文件并遍历每个字节

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

#1楼

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 2.5-2.7

with open("myfile", "rb") as f:

byte = f.read(1)

while byte != "":

# Do stuff with byte.

byte = f.read(1)

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

from __future__ import with_statement

在2.6中是不需要的。

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""评估为false的事实。 这使代码在2.6和3.x之间兼容,而无需进行任何更改。 如果从字节模式更改为文本模式或相反,也可以避免更改条件。

with open("myfile", "rb") as f:

byte = f.read(1)

while byte:

# Do stuff with byte.

byte = f.read(1)

#2楼

如果文件不是太大,则将其保存在内存中是一个问题:

with open("filename", "rb") as f:

bytes_read = f.read()

for b in bytes_read:

process_byte(b)

其中process_byte表示要对传入的字节执行的某些操作。

如果要一次处理一个块:

with open("filename", "rb") as f:

bytes_read = f.read(CHUNKSIZE)

while bytes_read:

for b in bytes_read:

process_byte(b)

bytes_read = f.read(CHUNKSIZE)

with语句在Python 2.5及更高版本中可用。

#3楼

该生成器从文件中产生字节,并分块读取文件:

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文档。

#4楼

总结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缓冲区-无需读取块

干式原理-不要重复读取行

with语句可确保关闭文件干净

如果没有更多的字节(不是字节为零),则“ byte”的计算结果为false

或使用JF Sebastians解决方案提高速度

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)

#5楼

with open(filename, 'rb') as file:

for byte in iter(lambda: file.read(1), b''):

# Do stuff with byte

它调用file.read(1)直到不返回任何内容b'' (空字节串)。 对于大文件,内存不会无限增长。 您可以将buffering=0传递给open() ,以禁用缓冲-它保证每次迭代仅读取一个字节(慢速)。

with -statement会自动关闭文件-包括下面的代码引发异常的情况。

尽管默认情况下存在内部缓冲,但是每次处理一个字节仍然效率低下。 例如,这是blackhole.py实用程序,可以使用它所提供的所有内容:

#!/usr/bin/env python3

"""Discard all input. `cat > /dev/null` analog."""

import sys

from functools import partial

from collections import deque

chunksize = int(sys.argv[1]) if len(sys.argv) > 1 else (1 << 15)

deque(iter(partial(sys.stdin.detach().read, chunksize), b''), maxlen=0)

例:

$ dd if=/dev/zero bs=1M count=1000 | python3 blackhole.py

它处理〜1.5 Gb / s的时chunksize == 32768我的机器,只〜7.5 MB的/秒时chunksize == 1 。 也就是说,一次读取一个字节要慢200倍。 考虑到这一点,如果你可以重写你的处理同时使用多个字节, 如果你需要的性能。

mmap允许您同时将文件视为bytearray数组和文件对象。 如果您需要访问两个接口,它可以替代将整个文件加载到内存中的方法。 特别是,您可以使用普通for -loop一次遍历一个内存映射文件一个字节:

from mmap import ACCESS_READ, mmap

with open(filename, 'rb', 0) as f, mmap(f.fileno(), 0, access=ACCESS_READ) as s:

for byte in s: # length is equal to the current file size

# Do stuff with byte

mmap支持切片符号。 例如, mm[i:i+len]从文件开始,从位置i返回len个字节。 Python 3.2之前不支持上下文管理器协议。 在这种情况下,您需要显式调用mm.close() 。 使用mmap遍历每个字节要比file.read(1)消耗更多的内存,但是mmap快一个数量级。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值