我试图使用struct.unpack()来拆分以ASCII字符串结尾的数据记录.
记录(恰好是TomTom ov2记录)具有这种格式(存储的小端):
> 1个字节
> 4字节int表示总记录大小(包括此字段)
> 4字节int
> 4字节int
>可变长度字符串,以null结尾
unpack()要求字符串的长度包含在传递它的格式中.我可以使用第二个字段和记录其余部分的已知大小–13个字节 – 来获取字符串长度:
str_len = struct.unpack("<xi",record[:5])[0] - 13 fmt = "<biii{0}s".format(str_len)
然后继续完全解包,但由于字符串是空终止的,我真的希望unpack()会为我做.如果我遇到一个不包含自己大小的结构,那么这也很好.
我怎么能做到这一点?
解决方法
我制作了两个新功能,可用作标准包和解包功能的直接替换.它们都支持’z’字符来打包/解包ASCIIZ字符串.格式字符串中’z’字符的出现位置或出现次数没有限制:
import struct def unpack (format,buffer) : while True : pos = format.find ('z') if pos < 0 : break asciiz_start = struct.calcsize (format[:pos]) asciiz_len = buffer[asciiz_start:].find('\0') format = '%s%dsx%s' % (format[:pos],asciiz_len,format[pos+1:]) return struct.unpack (format,buffer) def pack (format,*args) : new_format = '' arg_number = 0 for c in format : if c == 'z' : new_format += '%ds' % (len(args[arg_number])+1) arg_number += 1 else : new_format += c if c in 'cbB?hHiIlLqQfdspP' : arg_number += 1 return struct.pack (new_format,*args)
以下是如何使用它们的示例:
>>> from struct_z import pack,unpack >>> line = pack ('<izizi',1,'Hello',2,' world!',3) >>> print line.encode('hex') 0100000048656c6c6f000200000020776f726c64210003000000 >>> print unpack ('<izizi',line) (1,3) >>>