2011-03-01 114 views
4

我有这个小问题,在过去的一个小时左右一直在困扰着我。Python Struct解压缩

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

这个包的结果是B“\ X00 \ x01-”

我遇到的问题是,我无法弄清楚如何拆包结果B'\ X00 \ X01 - '只是' - ',是的。我知道我可以把前面的垃圾清除掉,但它会变得更复杂一些。我试图在这里简化它。希望有人能帮助我。 :)

+0

也许我误解了,但http://docs.python.org/library/struct.html#struct.unpack – ide 2011-03-02 00:09:48

回答

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

如何你准确地解开包装?

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

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)) 
# '-' 

一般来说,如果你不知道字符串是如何打包的,那么没有确定的方法来恢复dat一个。你只需要猜测!

如果你知道 组成的字符串长度的数据,然后字符串本身,那么你 可以尝试尝试和错误:

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,但是。我不确定。

+0

好的。现在如果你不知道字符串的实际长度怎么办? – dbdii407 2011-03-02 00:26:27

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 
+0

'struct.calcsize(“> h”)'是一种比较详细的写'2'的方式 – 2011-03-02 08:08:48

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()