IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    [原]4.1.2.3 格式字符例子

    caimouse发表于 2015-10-30 21:59:50
    love 0

    采用小端模式进行解包,并赋值例子:

    #python 3.4.3
    import struct
    
    record = b'raymond   \x32\x12\x08\x01\x08'
    name, serialnum, school, gradelevel = struct.unpack('<10sHHb', record)
    print(name, serialnum, school, gradelevel)

    结果输出如下:

    b'raymond   ' 4658 264 8

    在这里采用struct.unpack解包,把记录record二进制流进行分解,把四项数据保存在name, serialnum, school, gradelevel里面,最后把它们显示出来。其中'<10sHHb'是表示采用小端模式,10个字符,两个无符号数,一个有符号字符类型。

     

    采用命名元组保存解包的数据例子:

    #python 3.4.3
    import struct
    from collections import namedtuple
    
    record = b'raymond   \x32\x12\x08\x01\x08'
    name, serialnum, school, gradelevel = struct.unpack('<10sHHb', record)
    print(name, serialnum, school, gradelevel)
    
    Student = namedtuple('Student', 'name serialnum school gradelevel')
    #解包数据保存到元组
    print(Student._make(struct.unpack('<10sHHb', record)))

    结果输出如下:

    b'raymond   ' 4658 264 8

    Student(name=b'raymond   ', serialnum=4658, school=264, gradelevel=8)

    在这个例子里,主要使用namedtuple,然后直接调用_make方法,把解包出来的数据,直接保存在命名元组里,不需要创建新的变量保存数据,对于数据的结构化管理很方便。相当二进制流过来解包,直接生成一个结构化的元组。

     

    默认数据对齐方式的例子:

    #python 3.4.3

    import struct

     

    print('ci:', struct.pack('ci', b'*', 0x12131415))

    print('ic:', struct.pack('ic', 0x12131415, b'*'))

    print('ci size:', struct.calcsize('ci'))

    print('ic size:', struct.calcsize('ic'))

    结果输出如下:

    ci: b'*\x00\x00\x00\x15\x14\x13\x12'

    ic: b'\x15\x14\x13\x12*'

    ci size: 8

    ic size: 5

    从这个例子里,可以看到同样是两个类型c和i的格式,只是排列不一样,导致最后打包出来的二进制流大小不一样,就是由于在连续两个类型之间会产生补齐字符的情况。如果在同一个主机或者同一台电脑里使用下,对于是否添加补充字符是一样的,对于不同的电脑可能是不一样的。所以一般来说对于不同电脑之间的通讯,就需要采用不补充的方式进行填充了,把例子修改如下:

    #python 3.4.3

    import struct

     

    print('=ci:', struct.pack('=ci', b'*', 0x12131415))

    print('=ic:', struct.pack('=ic', 0x12131415, b'*'))

    print('=ci size:', struct.calcsize('=ci'))

    print('=ic size:', struct.calcsize('=ic'))

    结果输出如下:

    =ci: b'*\x15\x14\x13\x12'

    =ic: b'\x15\x14\x13\x12*'

    =ci size: 5

    =ic size: 5

     

    以四字对齐,在结构后尾补齐的例子:

    #python 3.4.3

    import struct

     

    print('llh:', struct.pack('llh', 1, 2, 3))

    print('llh0l:', struct.pack('llh0l', 1, 2, 3))

    print('llb0l:', struct.pack('llh0l', 1, 2, 3))

    结果输出如下:

    llh: b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00'

    llh0l: b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00'

    llb0l: b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00'

    在这个例子里,通过格式串后尾添加零个l的方式来进行四字节对齐,要注意这里格式字符l,而不是数字1。

    4.1.3 类struct

    在struct模块里,定义一个类struct,主要以下方法:

    class struct.Struct(format)

    返回一个可以按格式format进行操作二进制数据的Struct对象。如果只有一种格式进行解包和打包时,采用此对象比使用函数更高效,因为格式字符串只需要进行处理一次,就可以对不同数据进行解包和打包的操作了。

    此对象支持以下方法和属性:

    pack(v1, v2, ...) 

    与pack()函数功能一样,用已经编译好的格式字符串打包。

     

    pack_into(buffer, offset, v1, v2, ...) 

    与pack_into()函数功能一样,用已经编译好的格式字符串打包。

     

    unpack(buffer) 

    与unpack()函数功能一样,用已经编译好的格式字符串解包。

     

    unpack_from(buffer, offset=0) 

    与unpack_from()函数功能一样,用已经编译好的格式字符串解包。

     

    iter_unpack(buffer) 

    与iter_unpack()函数功能一样,用已经编译好的格式字符串解包。

     

    format 

    保存构造时传入格式字符串。

     

    size 

    根据格式字符串进行计算出来需要二进制缓冲区的大小。

    例子:

    #python 3.4.3

    import struct

     

    fmt = struct.Struct('llh')

    print(fmt.format)

    print(fmt.size)

     

    encode = fmt.pack(1, 2, 3)

    print(encode)

    print(fmt.unpack(encode))

    结果输出如下:

    b'llh'

    10

    b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00'

    (1, 2, 3)

     

    蔡军生  QQ:9073204  深圳


沪ICP备19023445号-2号
友情链接