维斯有条河    科学与耕耘

【Python】SF社区问答:关于 struct.pack  30 Jan 2015



本文选自在 SegmentFault 上我的回答,链接戳这里


问题引用:

关于 struct.pack 的理解以及以下代码的解释

    def setUTF(self, value):

        tag = '>h' if self.endian == HIGHT_ENDIAN else 'h'
        length = len(value)
        self.buffer += (struct.pack(tag, length))

        tag = '%ss' % (length)
        self.buffer += (struct.pack(tag, value))
        return True

答:

因为涉及二进制串和字节处理,所以包含的知识是比较底层的
首先要知道 struct 中的 pack 和 unpack 是用来完成数据结构和字节流之间转换的
也就是说,这两个函数是在转换数据的表示形式,并不会改变数据
比如 int a = 4; 这里的 a 转换通过'i' format 成字节流为: \x04\x00\x00\x00 (大端序为 \x00\x00\x00\x04)
以上或者反过来


那么简洁地说
  • 为什么要转换?
    为了迎合处理字节流,比如 构造网络包来发送,或者解析接收的网络包
  • 怎么转?
    这就是函数(主要就是 pack 和 unpack)的使用方法
    pack(format, value1, value2...)
    unpack(format, string)
    pack函数将普通的数据结构转成字节流
    你自然要提供一个 format, 这个 format 描述了你要操作的后面许多value的数据类型,从而按照这个描述生成的有意义的字节流
    而接收到的字节流或者生成的字节流,可以通过unpack函数来解析
    一大段字节来了,你要解析,自然需要描述一下这个字节流我该在哪里切分一下,应该用什么顺序等
    这就是format在做的事情
  • format 该怎么写?
    请自行查询这里 format 的语法
    特别的,由于系统本身处理字符串的差异
    在描述数据类型的format参数的开头,也可能有(可缺省)描述format方式的符号(比如描述字节顺序)

所以,我们来看你的这段代码:
  • 代码中的tag,即为 format 变量。
    tag = '>h' if self.endian == HIGHT_ENDIAN else 'h'
    这里通过判断字节顺序,来判断是否添加 大端字节序描述符‘>’ 到format前
    'h'在format语法中代表 2字节长度的 C语言 short类型(Python中的 integer )
  • 保存value长度
    length = len(value)
    self.buffer += (struct.pack(tag, length))
    求的value的长度,现在的tag值为“h”或者“>h”
    表示长度length, 调用函数生成字节流添加到buffer的尾端
  • 保存value的值
    tag = '%ss' % (length)
    self.buffer += (struct.pack(tag, value))
    先生成描述value的format,然后pack,添加到buffer尾端


About
  • Copyright ©2016 _v7__     Home: github.com/vince67     Blog:   维斯有条河     Email:      友情链接: 张小洋的布劳阁