Python Struct Unpack

时间:2011-03-01 23:58:47

标签: python struct

我有这个小问题,在过去一小时左右一直困扰着我。

string = b'-'
t = struct.pack(">h%ds" % len(string), len(string), string)
print(t)

这个包的结果是b'\ x00 \ x01 - '

我遇到的问题是我无法弄清楚如何解压缩结果b'\ x00 \ x01-'以便它只是' - ',是的。我知道我可以删除前面的废话,但它会变得有点复杂。我试着在这里简化它。希望有人可以帮助我。 :)

5 个答案:

答案 0 :(得分:5)

通常,您不会使用struct.pack将长度标头和值放在一起。相反,您只需执行struct.pack(">h", len(data)),通过线路发送(例如在网络协议中),然后发送数据。无需创建新的字节缓冲区。

在您的情况下,您可以这样做:

dataLength, = struct.unpack(">h", t[:2])
data = t[2:2+dataLength]

但正如我所说的,如果您有一个基于套接字的应用程序,它就像这样:

header = receive(2)
dataLength, = struct.unpack(">h", header)
data = receive(dataLength)

答案 1 :(得分:3)

import struct
string = b'-'
fmt=">h%ds" % len(string)

这里包装了长度和字符串:

t = struct.pack(fmt, len(string), string)
print(repr(t))
# '\x00\x01-'

所以当你解压缩时,你应该期望得到两个值,即长度和字符串:

length,string2=struct.unpack(fmt,t)
print(repr(string2))
# '-'

通常,如果您不知道字符串是如何打包的,那么就没有可靠的方法来恢复数据。你只需要猜测!

如果你知道这些数据 由字符串的长度组成,然后是字符串本身,然后是你 可以尝试反复尝试:

import struct
string = b'-'
fmt=">h%ds" % len(string)
t = struct.pack(fmt, len(string), string)
print(repr(t))

for endian in ('>','<'):
    for fmt,size in (('b',1),('B',1),('h',2),('H',2),('i',4),('I',4),
                     ('l',4),('L',4),('q',8),('Q',8)):
        fmt=endian+fmt
        try:
            length,=struct.unpack(fmt,t[:size])
        except struct.error:
            pass
        else:
            fmt=fmt+'{0}s'.format(length)
            try:
                length,string2=struct.unpack(fmt,t)
            except struct.error:
                pass
            else:
                print(fmt,length,string2)
# ('>h1s', 1, '-')
# ('>H1s', 1, '-')

有可能组成一个不明确的字符串t,它有多个有效的解包,这会导致不同的string2 s。我不确定。

答案 2 :(得分:1)

让我们假设data是一大块字节,并且您已成功解析出第一个posn字节。这个字节块的文档说明下一个项目是一个字节字符串,前面是16位有符号(不太可能,但你确实说h格式)bigendian整数。这是做什么的:

nbytes, = struct.unpack('>h', data[posn:posn+2]
posn += 2
the_string = data[posn:posn+nbytes]
posn += nbytes

现在你已经为下一个项目准备好了。

注意:如果您编写的代码仅限于Python 2.5或更高版本,则可以使用unpack_from()

答案 3 :(得分:0)

struct模块专为固定格式的数据块而设计。但是,您可以使用以下代码:

import struct
t=b'\x00\x01-'
(length,)=struct.unpack_from(">h", t)
(text,)=struct.unpack_from("%ds"%length, t, struct.calcsize(">h"))
print text

答案 4 :(得分:-1)

你究竟如何拆箱?

>>> string = b'-'
>>> format = '>h%ds' % len(string)
>>> format
'>h1s'
>>> struct.calcsize(format)
3

对于unpack(fmt, string)len(string)必须等于struct.calcsize(fmt)。因此,解压缩的数据不可能只是'-'

可是:

>>> t = b'\x00\x01-'
>>> length, data = struct.unpack(format, t)
>>> length, data
(1, '-')

现在您可以使用data