热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

python教程分享Python基础笔记之struct和格式化字符

目录简介struct中的方法格式字符串字节顺序,大小和对齐方式格式字符格式数字格式字符格式字符串填充的影响复杂应用总结简介文件的存储内容有两种方式,一种是二进制,一种是文本的形式。
目录
  • 简介
  • struct中的方法
  • 格式字符串
    • 字节顺序,大小和对齐方式
    • 格式字符
      • 格式数字
      • 格式字符
      • 格式字符串
      • 填充的影响
      • 复杂应用
  • 总结

    简介

    文件的存储内容有两种方式,一种是二进制,一种是文本的形式。如果是以文本的形式存储在文件中,那么从文件中读取的时候就会遇到一个将文本转换为python中数据类型的问题。实际上即使是文本的形式存储,存储的数据也是也是有结构的,因为python底层是用c来编写的,这里我们也称之为c结构。

    lib/struct.py 就是负责进行这种结构转换的模块。

    struct中的方法

    先看下struct的定义:

    __all__ = [      # functions      'calcsize', 'pack', 'pack_into', 'unpack', 'unpack_from',      'iter_unpack',        # classes      'struct',        # exceptions      'error'      ]

    其中有6个方法,1个异常。

    我们主要来看这6个方法的使用:

    方法名 作用
    struct.pack(format, v1, v2, …) 返回一个 bytes 对象,其中包含根据格式字符串 format 打包的值 v1, v2, … 参数个数必须与格式字符串所要求的值完全匹配。
    struct.pack_into(format, buffer, offset, v1, v2, …) 根据格式字符串 format 打包 v1, v2, … 并将打包的字节串从 offset 开始的位置写入可写缓冲区 buffer 。 请注意 offset 是必需的参数。
    struct.unpack(format, buffer) 根据格式字符串 format 从缓冲区 buffer 解包(假定是由 pack(format, …) 打包)。 返回的结果为一个元组,即使其只包含一个条目。 缓冲区的字节大小必须匹配格式所要求的大小。
    struct.unpack_from(format, /, buffer, offset=0) 从位置 offset 开始对 buffer 根据格式字符串 format 进行解包。 结果为一个元组,即使其中只包含一个条目。
    struct.iter_unpack(format, buffer) 根据格式字符串 format 以迭代方式从缓冲区 buffer 解包。 此函数返回一个迭代器,它将从缓冲区读取相同大小的块直至其内容全部耗尽。
    struct.calcsize(format) 返回与格式字符串 format 相对应的结构的大小(亦即 pack(format, …) 所产生的字节串对象的大小)。

    这些方法主要就是打包和解包的操作,其中一个非常重要的参数就是format,也被成为格式字符串,它指定了每个字符串被打包的格式。

    格式字符串

    格式字符串是用来在打包和解包数据时指定数据格式的机制。 它们使用指定被打包/解包数据类型的 格式字符 进行构建。 此外,还有一些特殊字符用来控制 字节顺序,大小和对齐方式。

    字节顺序,大小和对齐方式

    默认情况下,c类型以机器的本机格式和字节顺序表示,并在必要时通过填充字节进行正确对齐(根据c编译器使用的规则)。

    我们也可以手动指定格式字符串的字节顺序,大小和对齐方式:

    字符 字节顺序 大小 对齐方式
    @ 按原字节 按原字节 按原字节
    = 按原字节 标准
    < 小端 标准
    > 大端 标准
    ! 网络(=大端) 标准

    大端和小端是两种数据存储方式。

    第一种big endian将高位的字节存储在起始地址

    Python基础笔记之struct和格式化字符

    第二种little endian将地位的字节存储在起始地址

    Python基础笔记之struct和格式化字符

    其实big endian更加符合人类的读写习惯,而little endian更加符合机器的读写习惯。

    目前主流的两大cpu阵营中,powerpc系列采用big endian方式存储数据,而x86系列则采用little endian方式存储数据。

    如果不同的cpu架构直接进行通信,就由可能因为读取顺序的不同而产生问题。

    填充只会在连续结构成员之间自动添加。 填充不会添加到已编码结构的开头和末尾。

    当使用非原字节大小和对齐方式即 &#39;<&#39;, &#39;>&#39;, &#39;=&#39;, and &#39;!&#39; 时不会添加任何填充。

    格式字符

    我们来看下字符都有哪些格式:

    格式 c 类型 python 类型 标准大小(字节)
    x 填充字节  
    c char 长度为 1 的字节串 1
    b signed char 整数 1
    b unsigned char 整数 1
    ? _bool bool 1
    h short 整数 2
    h unsigned short 整数 2
    i int 整数 4
    i unsigned int 整数 4
    l long 整数 4
    l unsigned long 整数 4
    q long long 整数 8
    q unsigned long long 整数 8
    n ssize_t 整数  
    n size_t 整数  
    e (6) 浮点数 2
    f float 浮点数 4
    d double 浮点数 8
    s char[] 字节串  
    p char[] 字节串  
    p void * 整数  

    格式数字

    举个例子,比如我们要打包一个int对象,我们可以这样写:

    in [101]: from struct import *    in [102]: pack('i',10)  out[102]: b'nx00x00x00'    in [103]: unpack('i',b'nx00x00x00')  out[103]: (10,)      in [105]: calcsize('i')  out[105]: 4

    上面的例子中,我们打包了一个int对象10,然后又对其解包。并且计算了 i 这个格式的长度为4字节。

    大家可以看到输出结果是 b&#39;nx00x00x00&#39; ,这里不去深究这个输出到底是什么意思,开头的b表示的是byte,后面是byte的编码。

    格式字符之前可以带有整数重复计数。 例如,格式字符串 &#39;4h&#39; 的含义与 &#39;hhhh&#39; 完全相同。

    看下如何打包4个short类型:

    in [106]: pack('4h',2,3,4,5)  out[106]: b'x02x00x03x00x04x00x05x00'    in [107]: unpack('4h',b'x02x00x03x00x04x00x05x00')  out[107]: (2, 3, 4, 5)

    格式之间的空白字符会被忽略,但如果是struct.calcsize 方法的话格式字符中不可有空白字符。

    当使用某一种整数格式 (&#39;b&#39;, &#39;b&#39;, &#39;h&#39;, &#39;h&#39;, &#39;i&#39;, &#39;i&#39;, &#39;l&#39;, &#39;l&#39;, &#39;q&#39;, &#39;q&#39;) 打包值 x 时,如果 x 在该格式的有效范围之外则将引发 struct.error。

    格式字符

    除了数字之外,最常用的就是字符和字符串了。

    我们先看下怎么使用格式字符,因为字符的长度是1个字节,我们需要这样做:

    in [109]: pack('4c',b'a',b'b',b'c',b'd')  out[109]: b'abcd'    in [110]: unpack('4c',b'abcd')  out[110]: (b'a', b'b', b'c', b'd')    in [111]: calcsize('4c')  out[111]: 4

    字符前面的b,表示这是一个字符,否则将会被当做字符串。

    格式字符串

    再看下字符串的格式:

    in [114]: pack('4s',b'abcd')  out[114]: b'abcd'    in [115]: unpack('4s',b'abcd')  out[115]: (b'abcd',)    in [116]: calcsize('4s')  out[116]: 4    in [117]: calcsize('s')  out[117]: 1

    可以看到对于字符串来说calcsize返回的是字节的长度。

    填充的影响

    格式字符的顺序可能对大小产生影响,因为满足对齐要求所需的填充是不同的:

    >>> pack('ci', b'*', 0x12131415)  b'*x00x00x00x12x13x14x15'  >>> pack('ic', 0x12131415, b'*')  b'x12x13x14x15*'  >>> calcsize('ci')  8  >>> calcsize('ic')  5

    下面的例子我们将会展示如何手动影响填充效果:

    in [120]: pack('llh',1, 2, 3)  out[120]: b'x01x00x00x00x00x00x00x00x02x00x00x00x00x00x00x00x03x00'

    上面的例子中,我们打包1,2,3这三个数字,但是格式不一样,分别是long,long,short。

    因为long是4个字节,short是2个字节,所以本质上是不对齐的。

    如果想要对齐,我们可以在后面再加上 0l 表示0个long,从而进行手动填充:

    in [118]: pack('llh0l', 1, 2, 3)  out[118]: b'x01x00x00x00x00x00x00x00x02x00x00x00x00x00x00x00x03x00x00x00x00x00x00x00'    in [122]: unpack('llh0l',b'x01x00x00x00x00x00x00x00x02x00x00x00x00x00x00x00x03x00x00x00x00x00x00x00')  out[122]: (1, 2, 3)

    复杂应用

    最后看一个复杂点的应用,这个应用中直接从unpack出来的数据读取到元组中:

    >>> record = b'raymond   x32x12x08x01x08'  >>> name, serialnum, school, gradelevel = unpack('<10shhb', record)    >>> from collections import namedtuple  >>> student = namedtuple('student', 'name serialnum school gradelevel')  >>> student._make(unpack('<10shhb', record))  student(name=b'raymond   ', serialnum=4658, school=264, gradelevel=8)

    总结

    到此这篇关于python基础笔记之struct和格式化字符的文章就介绍到这了,更多相关python struct和格式化字符内容请搜索<编程笔记>以前的文章或继续浏览下面的相关文章希望大家以后多多支持<编程笔记>!

    需要了解更多python教程分享Python基础笔记之struct和格式化字符,都可以关注python教程分享栏目&#8212;编程笔记


    推荐阅读
    • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
    • 嵌入式处理器的架构与内核发展历程
      本文主要介绍了嵌入式处理器的架构与内核发展历程,包括不同架构的指令集的变化,以及内核的流水线和结构。通过对ARM架构的分析,可以更好地理解嵌入式处理器的架构与内核的关系。 ... [详细]
    • 本文介绍了一种轻巧方便的工具——集算器,通过使用集算器可以将文本日志变成结构化数据,然后可以使用SQL式查询。集算器利用集算语言的优点,将日志内容结构化为数据表结构,SPL支持直接对结构化的文件进行SQL查询,不再需要安装配置第三方数据库软件。本文还详细介绍了具体的实施过程。 ... [详细]
    • 本文介绍了一种图的存储和遍历方法——链式前向星法,该方法在存储带边权的图时时间效率比vector略高且节省空间。然而,链式前向星法存图的最大问题是对一个点的出边进行排序去重不容易,但在平行边无所谓的情况下选择这个方法是非常明智的。文章还提及了图中搜索树的父子关系一般不是很重要,同时给出了相应的代码示例。 ... [详细]
    • 一、Hadoop来历Hadoop的思想来源于Google在做搜索引擎的时候出现一个很大的问题就是这么多网页我如何才能以最快的速度来搜索到,由于这个问题Google发明 ... [详细]
    • 本文详细介绍了SQL日志收缩的方法,包括截断日志和删除不需要的旧日志记录。通过备份日志和使用DBCC SHRINKFILE命令可以实现日志的收缩。同时,还介绍了截断日志的原理和注意事项,包括不能截断事务日志的活动部分和MinLSN的确定方法。通过本文的方法,可以有效减小逻辑日志的大小,提高数据库的性能。 ... [详细]
    • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
    • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
    • 开发笔记:select from具体执行相关知识介绍及案例分析
      本文由编程笔记小编整理,主要介绍了select from具体执行相关的知识,包括数据插入、查询最小rowID、查询每个重复名字的最小rowID、删除重复数据等操作,并提供了案例分析。希望对读者有一定的参考价值。 ... [详细]
    • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
    • CentOS 7部署KVM虚拟化环境之一架构介绍
      本文介绍了CentOS 7部署KVM虚拟化环境的架构,详细解释了虚拟化技术的概念和原理,包括全虚拟化和半虚拟化。同时介绍了虚拟机的概念和虚拟化软件的作用。 ... [详细]
    • Oracle优化新常态的五大禁止及其性能隐患
      本文介绍了Oracle优化新常态中的五大禁止措施,包括禁止外键、禁止视图、禁止触发器、禁止存储过程和禁止JOB,并分析了这些禁止措施可能带来的性能隐患。文章还讨论了这些禁止措施在C/S架构和B/S架构中的不同应用情况,并提出了解决方案。 ... [详细]
    • 全面介绍Windows内存管理机制及C++内存分配实例(四):内存映射文件
      本文旨在全面介绍Windows内存管理机制及C++内存分配实例中的内存映射文件。通过对内存映射文件的使用场合和与虚拟内存的区别进行解析,帮助读者更好地理解操作系统的内存管理机制。同时,本文还提供了相关章节的链接,方便读者深入学习Windows内存管理及C++内存分配实例的其他内容。 ... [详细]
    • 本文概述了JNI的原理以及常用方法。JNI提供了一种Java字节码调用C/C++的解决方案,但引用类型不能直接在Native层使用,需要进行类型转化。多维数组(包括二维数组)都是引用类型,需要使用jobjectArray类型来存取其值。此外,由于Java支持函数重载,根据函数名无法找到对应的JNI函数,因此介绍了JNI函数签名信息的解决方案。 ... [详细]
    • 如何使用PLEX播放组播、抓取信号源以及设置路由器
      本文介绍了如何使用PLEX播放组播、抓取信号源以及设置路由器。通过使用xTeve软件和M3U源,用户可以在PLEX上实现直播功能,并且可以自动匹配EPG信息和定时录制节目。同时,本文还提供了从华为itv盒子提取组播地址的方法以及如何在ASUS固件路由器上设置IPTV。在使用PLEX之前,建议先使用VLC测试是否可以正常播放UDPXY转发的iptv流。最后,本文还介绍了docker版xTeve的设置方法。 ... [详细]
    author-avatar
    Sunshine5585
    这个家伙很懒,什么也没留下!
    PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
    Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有