4

[oeasy]python0019_ 打包和解包_struct_pack_unpack

 1 year ago
source link: https://blog.51cto.com/oeasy/5880316
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

打包和解包

回忆上次内容

  • ASCII 由这样几类字符构成
  • 英文大写字符
  • 英文小写字符
  • 电报时代对于英文、数字的编码
  • 使用的是摩斯电码
[oeasy]python0019_ 打包和解包_struct_pack_unpack_解包
  • 这摩斯电码是3进制的编码方式
  • 怎么演化成ascii这种0101的二进制编码的呢?🤔

回到 ASCII 码

  • 电报传过来的信号需要记录下来
  • 于是有了电传打字机(tele-typewriter)
  • 电传打字机需要统一的编码字母和数字
  • ASCII的第一个商业用途
  • 是作为一个七位电传打字机(tele-typewriter)代码
[oeasy]python0019_ 打包和解包_struct_pack_unpack_解包_02
  • 要把滴、答、停的电报信号
  • 变成0和1的二进制信号

ASCII的演化(evolve)

  • 1960年10月6日
  • 美国标准协会(ASA)X3的首次会议
  • ASCII标准的工作开始了
  • 美国标准协会
  • 现为美国国家标准协会
  • American National Standards Institute
  • 简称ANSI
  • 开始敲定ASCII具体编码
[oeasy]python0019_ 打包和解包_struct_pack_unpack_封包_03
  • 贝尔公司主要经营电报电话
  • 第一次(ASA X3.4-1963)就明确
  • 大小写字母之间只差一个位
[oeasy]python0019_ 打包和解包_struct_pack_unpack_python_04
  • 否则错误编码一旦成为标准
  • 所有应用这种错误编码的文件
  • 就都废掉了
  • 我想把所有 ASCII 字符 0-127 全都打出来

 ​回忆show.py​

for n in range(0xff):
print(chr(n),end="")
if n % 16 == 0:
print()
  • 确实可以出来
[oeasy]python0019_ 打包和解包_struct_pack_unpack_解包_05
  • 这输出靠的是
  • 把序号转化成字符的函数
  • 但是没有看到0
  • 理论上在1之前
  • 仿佛被黑暗森林所吞没
  • 我能否将字节解码(decode)来干这个事?

struct

  • 首先是要获得从0到127的字节状态
  • struct 是一个包(module)
  • 导入struct包
[oeasy]python0019_ 打包和解包_struct_pack_unpack_python_06
  • struct是结构的意思
  • 来自于c里面常用类型的存储结构
  • 这个struct怎么用呢?
[oeasy]python0019_ 打包和解包_struct_pack_unpack_封包_07
  • 把数字变成字节的形态
  • 把0x61这个数字变成字节的形态
[oeasy]python0019_ 打包和解包_struct_pack_unpack_python_08
  • "a" 不是字符吗?🤔
  • 怎么成了字节了?

字节表示法

[oeasy]python0019_ 打包和解包_struct_pack_unpack_python_09
  • 注意"a"前面还有一个b
  • "a"是字符
  • b"a" 是字节

[oeasy]python0019_ 打包和解包_struct_pack_unpack_解包_10

  • 这两类型完全不同
  • 字节b"a"是什么呢?
  • 字节状态可以用两个16进制数来表示
  • 相当于b"\x61"
[oeasy]python0019_ 打包和解包_struct_pack_unpack_python_11
  • b"a" 和 b"\x61" 是同样的一个字节
  • 就是字符"a"在字节里的样子
[oeasy]python0019_ 打包和解包_struct_pack_unpack_python_12
  • 为了清楚起见
  • 把b"\x61"表示为b"a"
  • 这样也就直接看到了字符😂
  • 刚好ord("a") 就是 0x61
  • 如何理解struct.pack呢?

封包pack

  • 按要求把东西封进规定的封装里面
[oeasy]python0019_ 打包和解包_struct_pack_unpack_封包_13
  • 把数字封在1个Byte里面
  • 观察他的字节状态
import struct
for n in range(0,128):
b = struct.pack("b",n)
print(b,end=",")
  • 把从0-127的数字都封到字节里面
[oeasy]python0019_ 打包和解包_struct_pack_unpack_封包_14
  • 可以把数字转化成字节状态
  • 然后可以再把字节解码了
  • 好多的字节呀~😄
[oeasy]python0019_ 打包和解包_struct_pack_unpack_python_15
  • 从字节状态可以看到已经有
  • 0、1、2、3
  • 这里很明显能看到0
  • 还有0前面的一堆符号
  • A、B、C
  • a、b、c
  • \r、\n、\t
  • 这是啥意思?🤔
  • 怎么还能有两个字符呢?
  • 先加上换行
[oeasy]python0019_ 打包和解包_struct_pack_unpack_封包_16
  • 从0数到7
  • 再从0数到7
[oeasy]python0019_ 打包和解包_struct_pack_unpack_解包_17
  • 隐约看到了ascii码的结构
  • 我不想看字节状态呢
  • 我想看字符状态
  • 需要对字节状态解码(decode)
  • 也就是解包
  • struct.unpack
  • 这又是一圈
  • unpack
[oeasy]python0019_ 打包和解包_struct_pack_unpack_封包_18
  • 解包出来是序号
  • 先把0-127的数字都变成字节

封包再解包

import struct
for n in range(0,127):
b = struct.pack("b",n)
c = struct.unpack("b",b)[0]
print(chr(c),end="")
if n % 16 == 0:
print()
  • 依然要面对黑暗森林
[oeasy]python0019_ 打包和解包_struct_pack_unpack_解包_19

封包再解码

import struct
for n in range(0,127):
b = struct.pack("b",n)
s = b.decode("ascii")
print(s,end="")
if n % 16 == 0:
print()
  • 上面那片依然是全黑的?
[oeasy]python0019_ 打包和解包_struct_pack_unpack_封包_20
  • 和原来chr方法得到的结果差不多
  • 但是没有看到字符0
  • 仿佛被上面那片黑暗森林所吞没
  • 这可真可怕!
  • 我们先去总结一下吧
  • struct包可以让我们使用封包格式
  • 把数字封包到字节里
  • pack函数就是封包
  • unpack函数就是解封
  • 我们通过封到不同字节的数字
  • 遍历了一次ascii码
[oeasy]python0019_ 打包和解包_struct_pack_unpack_解包_21
  • 还是有那片黑色的区域
  • 好像是一片黑暗森林!
  • 那里面到底有些什么秘密?🤔

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK