这是一个在不使用文本字符串转换的情况下执行位操作的生成器.希望它更有效率. 🙂
为了测试它,我将范围(1024)中的所有数字写入BytesIO流,其行为类似于二进制文件.
from io import BytesIO
def tenbitread(f):
''' Generate 10 bit (unsigned) integers from a binary file '''
while True:
b = f.read(5)
if len(b) == 0:
break
n = int.from_bytes(b, 'big')
#Split n into 4 10 bit integers
t = []
for i in range(4):
t.append(n & 0x3ff)
n >>= 10
yield from reversed(t)
# Make some test data: all the integers in range(1024),
# and save it to a byte stream
buff = BytesIO()
maxi = 1024
n = 0
for i in range(maxi):
n = (n << 10) | i
#Convert the 40 bit integer to 5 bytes & write them
if i % 4 == 3:
buff.write(n.to_bytes(5, 'big'))
n = 0
# Rewind the stream so we can read from it
buff.seek(0)
# Read the data in 10 bit chunks
a = list(tenbitread(buff))
# Check it
print(a == list(range(maxi)))
产量
True
做列表(tenbitread(buff))是将生成器输出转换为列表的最简单方法,但您可以轻松地迭代值,例如
for v in tenbitread(buff):
要么
for i, v in enumerate(tenbitread(buff)):
如果你想要索引以及数据值.
这是生成器的little-endian版本,它提供与代码相同的结果.
def tenbitread(f):
''' Generate 10 bit (unsigned) integers from a binary file '''
while True:
b = f.read(5)
if not len(b):
break
n = int.from_bytes(b, 'little')
#Split n into 4 10 bit integers
for i in range(4):
yield n & 0x3ff
n >>= 10
我们可以通过“un-rolling”for循环来略微改进这个版本,这可以让我们摆脱最终的屏蔽和转移操作.
def tenbitread(f):
''' Generate 10 bit (unsigned) integers from a binary file '''
while True:
b = f.read(5)
if not len(b):
break
n = int.from_bytes(b, 'little')
#Split n into 4 10 bit integers
yield n & 0x3ff
n >>= 10
yield n & 0x3ff
n >>= 10
yield n & 0x3ff
n >>= 10
yield n
这应该提高一点……