您的位置:首页 > 编程语言 > Python开发

Python字节流打包拆包

2016-01-18 16:49 549 查看
Python提供了一个struct模块用于打包拆包

---------------------------------------------------------------------------

该模块的主要的方法:

  struct.pack(fmt,v1,v2,.....)

    将v1,v2等参数的值进行一层包装,包装的方法由fmt指定。被包装的参数必须严格符合fmt。最后返回一个包装后的字符串。

例如:

>>>import struct
>>>a = 20
>>>b = 200
>>>buff = struct.pack('ii',a,b) #转换成字节流,虽然还是字符串,但是可以用于封包传输
>>>print len(buff)
8 #可以看到长度为8个字节,正好是两个int型数据的长度
>>>print buff

#二进制是乱码
>>>print repr(buff)
'\x14\x00\x00\x00\xc8\x00\x00\x00' #其中十六进制的 0x00000014,0x000000c8分别表示20和200
>>>

  struct.unpack(fmt,string)

    解包。用pack打包,然后就可以用unpack解包了。返回一个由解包数据(string)得到的一个元组(tuple),即使仅有一个数据也会被解包成        元组。其中len(string) 必须等于 calcsize(fmt)

例如:

>>>struct.unpack('ii',buff)#接上面的例子已有打包好的数据buff

(20,200)

>>>

[b]  struct.calcsize(fmt)
[/b]

    这个就是用来计算fmt格式所描述的结构的大小。

例如:

>>>struct.calcsize('ii')

8

>>>

  [b]struct.[b]unpack_from(fmt,string,[b]offset[/b])[/b][/b]

    这个也是用来解包,与struct.unpack(fmt,string)类似,只是从参数string的偏移offset位置开始读

  [b]struct.[b]pack_into(fmt,[b][b][b][b][b]string[/b][/b],offset[/b][/b],v1,v2,.....[/b])[/b][/b]

    这个也是用来打包,与[b]struct.pack(fmt,v1,v2,.....)[/b]类似,只是从参数string的偏移offset位置开始写

---------------------------------------------------------------------------

格式字符串(format string)由一个或多个格式字符(format characters)组成,对于这些格式字符的描述参照Python manual

如下:

FormatC TypePythonNotes
xpad byteno value
ccharstring of length 1
bsignedcharinteger
Bunsignedcharinteger
?_Boolbool(1)
hshortinteger
Hunsignedshortinteger
iintinteger
Iunsignedintinteger or long
llonginteger
Lunsignedlonglong
qlonglonglong(2)
Qunsignedlonglonglong(2)
ffloatfloat
ddoublefloat
schar[]string
pchar[]string
Pvoid*long
---------------------------------------------------------------------------

一个例子

[python] view plaincopyprint?

<span style="font-size:13px;">import struct

# native byteorder

buffer = struct.pack("ihb", 1, 2, 3)

print repr(buffer)

print struct.unpack("ihb", buffer)

# data from a sequence, network byteorder

data = [1, 2, 3]

buffer = struct.pack("!ihb", *data)

print repr(buffer)

print struct.unpack("!ihb", buffer) </span>

Output:

'\x01\x00\x00\x00\x02\x00\x03'
(1, 2, 3)
'\x00\x00\x00\x01\x00\x02\x03'
(1, 2, 3)

首先将参数1,2,3打包,打包前1,2,3明显属于python数据类型中的integer,pack后就变成了C结构的二进制串,转成python的string类型来显示就是  '\x01\x00\x00\x00\x02\x00\x03'。由于本机是小端('little-endian',关于大端和小端的区别请参照Google),故而高位放在低地址段。i 代表C struct中的int类型,故而本机占4位,1则表示为01000000;h 代表C struct中的short类型,占2位,故表示为0200;同理b 代表C struct中的signed char类型,占1位,故而表示为03。

---------------------------------------------------------------------------

在Format string 的首位,有一个可选字符来决定大端和小端,列表如下:

CharacterByte orderSize and alignment
@nativenative
=nativestandard
<little-endianstandard
>big-endianstandard
!network (= big-endian)standard
如果没有附加,默认为@,即使用本机的字符顺序(大端or小端),对于C结构的大小和内存中的对齐方式也是与本机相一致的(native),比如有的机器integer为2位而有的机器则为四位;有的机器内存对其位四位对齐,有的则是n位对齐(n未知,我也不知道多少)。

还有一个标准的选项,被描述为:如果使用标准的,则任何类型都无内存对齐。

下面是官方解释:

The module defines the following exception and functions:

exception
struct.
error

Exception raised on various occasions; argument is a string describing what is wrong.

struct.
pack
(fmt, v1, v2, ...)
Return a string containing the values
v1, v2, ...
packed according to the given format. The arguments must match the values required by the format exactly.

struct.
pack_into
(fmt, buffer, offset, v1, v2, ...)
Pack the values
v1, v2, ...
according to the given format, write the packed bytes into the writable buffer starting at offset. Note that the offset is a required argument.

New in version 2.5.

struct.
unpack
(fmt, string)
Unpack the string (presumably packed by
pack(fmt, ...)
) according to the given format. The result is a tuple even if it contains exactly one item. The string must contain exactly the amount of data required by the format (
len(string)
must equal
calcsize(fmt)
).

struct.
unpack_from
(fmt, buffer[, offset=0])
Unpack the buffer according to the given format. The result is a tuple even if it contains exactly one item. The buffer must contain at least the amount of data required by the format (
len(buffer[offset:])
must be at least
calcsize(fmt)
).

New in version 2.5.

struct.
calcsize
(fmt)
Return the size of the struct (and hence of the string) corresponding to the given format.

比如刚才的小程序的后半部分,使用的format string中首位为!,即为大端模式标准对齐方式,故而输出的为'\x00\x00\x00\x01\x00\x02\x03',其中高位自己就被放在内存的高地址位了。

实际使用范例,解析二进制byte数组:

DateTime = struct.unpack_from('I',inData,1+singleLong*i)
dateList.append(DateTime[0])
#print(DateTime)
#时间点的数据
for j in range(0,ValueNum):
dataInTimeTemp = struct.unpack_from('I',inData,5+singleLong*i+DataByteLen*j)
# if PrecisionLen>=0:  #精度计算后的结果 ,可以先无视
#     dataInTime = dataInTimeTemp[0] / math.pow(10,PrecisionLen)

#寻找最大值
dataList.append(dataInTimeTemp[0])
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: