• Python中struct.pack()和struct.unpack()用法


    python中的struct主要是用来处理C结构数据的,读入时先转换为Python的字符串类型,然后再转换为Python的结构化类型,比如元组(tuple)啥的~。一般输入的渠道来源于文件或者网络的二进制流。

    struct模块中最重要的三个函数是pack(), unpack(), calcsize()

    #  按照给定的格式(fmt),把数据封装成字符串(实际上是类似于c结构体的字节流)
    pack(fmt, v1, v2, ...)
    
    # 按照给定的格式(fmt)解析字节流string,返回解析出来的tuple
    unpack(fmt, string)      
    
    # 计算给定的格式(fmt)占用多少字节的内存
    calcsize(fmt)
    

    上述fmt中,支持的格式为:

    FORMAT

    C TYPE

    PYTHON TYPE

    STANDARD SIZE

    NOTES

    x

    pad byte

    no value

       

    c

    char

    string of length 1

    1

     

    b

    signed char

    integer

    1

    (3)

    B

    unsigned char

    integer

    1

    (3)

    ?

    _Bool

    bool

    1

    (1)

    h

    short

    integer

    2

    (3)

    H

    unsigned short

    integer

    2

    (3)

    i

    int

    integer

    4

    (3)

    I

    unsigned int

    integer

    4

    (3)

    l

    long

    integer

    4

    (3)

    L

    unsigned long

    integer

    4

    (3)

    q

    long long

    integer

    8

    (2), (3)

    Q

    unsigned long long

    integer

    8

    (2), (3)

    f

    float

    float

    4

    (4)

    d

    double

    float

    8

    (4)

    s

    char[]

    string

       

    p

    char[]

    string

       

    P

    void *

    integer

     

    (5), (3)

    注1.q和Q只在机器支持64位操作时有意思

    注2.每个格式前可以有一个数字,表示个数

    注3.s格式表示一定长度的字符串,4s表示长度为4的字符串,但是p表示的是pascal字符串

    注4.P用来转换一个指针,其长度和机器字长相关

    注5.最后一个可以用来表示指针类型的,占4个字节

    为了同c中的结构体交换数据,还要考虑有的c或c++编译器使用了字节对齐,通常是以4个字节为单位的32位系统,故而struct根据本地机器字节顺序转换.可以用格式中的第一个字符来改变对齐方式.定义如下:

    CHARACTER

    BYTE ORDER

    SIZE

    ALIGNMENT

    @

    native

    native

    native

    =

    native

    standard

    none

    <

    little-endian

    standard

    none

    >

    big-endian

    standard

    none

    !

    network (= big-endian)

    standard

    none

     使用方法是放在fmt的第一个位置,就像’@5s6sif’

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

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

    1.2 struct.unpack(fmt,string)

    顾名思义,解包。比如pack打包,然后就可以用unpack解包了。返回一个由解包数据(string)得到的一个元组(tuple), 即使仅有一个数据也会被解包成元组。其中len(string) 必须等于 calcsize(fmt),这里面涉及到了一个calcsize函数。struct.calcsize(fmt):这个就是用来计算fmt格式所描述的结构的大小。

     2.代码示例

    import struct
    
    # native byteorder
    buffer = struct.pack("ihb", 1, 2, 3)
    print(repr(buffer))
    '''
    b'\x01\x00\x00\x00\x02\x00\x03'
    '''
    print(struct.unpack("ihb", buffer))
    '''
    (1, 2, 3)
    '''
    
    # data from a sequence, network byteorder
    data = [1, 2, 3]
    buffer = struct.pack("!ihb", *data)
    print(repr(buffer))
    '''
    b'\x00\x00\x00\x01\x00\x02\x03'
    '''
    print(struct.unpack("!ihb", buffer))
    '''
    (1, 2, 3)
    '''
    

    首先将参数1,2,3打包,打包前1,2,3明显属于python数据类型中的integer,pack后就变成了C结构的二进制串,转成 python的string类型来显示就是’\x01\x00\x00\x00\x02\x00\x03’。

    由于本机是小端(‘little- endian’), 故而高位放在低地址段。

    i 代表C struct中的int类型,故而本机占4位,1则表示为01000000; h 代表C struct中的short类型,占2位,故表示为0200; 同理b 代表C struct中的signed char类型,占1位,故而表示为03。

    其他结构的转换也类似,有些特别的可以参考官方文档的Manual。

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

    CHARACTER

    BYTE ORDER

    SIZE

    ALIGNMENT

    @

    native

    native

    native

    =

    native

    standard

    none

    <

    little-endian

    standard

    none

    >

    big-endian

    standard

    none

    !

    network (= big-endian)

    standard

    none

    如果没有附加,默认为@,即使用本机的字符顺序(大端or小端),对于C结构的大小和内存中的对齐方式也是与本机相一致的(native),比如有的机器integer为2位而有的机器则为四位;有的机器内存对其位四位对齐,有的则是n位对齐(n未知,我也不知道多少)。

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

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

    struct的pack函数把任意数据类型变成bytes:

    import struct
    struct.pack('>I', 10240099)
    b'\x00\x9c@c'
    

    pack的第一个参数是处理指令,’>I’的意思是:

    >表示字节顺序是big-endian,也就是网络序,I表示4字节无符号整数。

    后面的参数个数要和处理指令一致。

    unpack把bytes变成相应的数据类型:

    struct.unpack('>IH', b'\xf0\xf0\xf0\xf0\x80\x80')
    (4042322160, 32896)
    

    根据>IH的说明,后面的bytes依次变为I:4字节无符号整数和H:2字节无符号整数。

    calcsize查看fmt所占的字节

    size = struct.calcsize("!iIHs")
    11
    

      

  • 相关阅读:
    flink 读取kafka 数据,partition分配
    Flink 报错 "Could not find a suitable table factory for 'org.apache.flink.table.factories.StreamTableSourceFactory' in the classpath"
    flume接收http请求,并将数据写到kafka
    【翻译】Flume 1.8.0 User Guide(用户指南) Processors
    【翻译】Flume 1.8.0 User Guide(用户指南) Channel
    【翻译】Flume 1.8.0 User Guide(用户指南) Sink
    【翻译】Flume 1.8.0 User Guide(用户指南) source
    【翻译】Flume 1.8.0 User Guide(用户指南)
    Apache Flink 简单安装
    Java之使用IDE
  • 原文地址:https://www.cnblogs.com/yoyo1216/p/15099170.html
Copyright © 2020-2023  润新知