我有一个二进制文件,其中包含4字节的二进制值,每个值代表一组两个short int
。我知道我可以将一个4字节的二进制值解压缩成两个短整数,如下所示:
from struct import unpack
fval = b'\xba\x1e\x99\x01' #actualy read from some file
qualdip, azi = unpack('hh', fval)
print(type(qualdip), qualdip)
print(type(azi), azi)
>>> <class 'int'> 7866
>>> <class 'int'> 409
现在,我想解压缩整个缓冲区。我正在做的那一刻:
qualdips = []
azis = []
with open(bfile, 'rb') as buf:
fval = buf.read(4)
while fval:
qualdip, azi = unpack('hh', fval)
azis.append(azi)
qualdips.append(qualdip)
fval = buf.read(4)
对于一个277MB的文件,这需要花费一分多钟时间,并且似乎会产生巨大的内存开销。
我想将整个filebuffer直接解压缩到两个变量中。我该如何做到这一点?
我怀疑struct.unpack_from
是我的朋友,但我不确定如何制定格式。
with open(bfile, 'rb') as buf:
qualdip, azi = unpack_from('hh', buf)
只提取两个值,并且(我知道我的文件的元素数量)
with open(bfile, 'rb') as buf:
qualdip, azi = unpack_from('72457091h72457091h', buf)
期望这个荒谬的输出变量。所以:
如何我将整个文件缓冲区直接解压缩到两个变量中?
答案 0 :(得分:1)
我不知道将值直接解压缩到两个列表中的方法,但是您可以将整个文件解压缩为一个元组,然后将其分成两部分:
fval = b'\xba\x1e\x99\x01' * 3
unpacked= unpack('3h3h', fval)
qualdip = unpacked[0::2]
azi = unpacked[1::2]
或者,使用islice
创建iterator,这将减少内存消耗。
qualdip = islice(unpacked, 0, None, 2)
azi = islice(unpacked, 1, None, 2)
答案 1 :(得分:0)
我认为这可能是一种更快捷的方法:
import os
import struct
def pairwise(iterable):
"s -> (s0,s1), (s2,s3), (s4, s5), ..."
a = iter(iterable)
return zip(a, a)
bfile = 'bfile.bin'
filesize = os.stat(bfile).st_size
numvals = filesize // 2
with open(bfile, 'rb') as bf:
fmt = '{}h'.format(numvals)
values = struct.unpack(fmt, str(bf.read()))
qualdips, azis = zip(*pairwise(values))