天天看點

「oeasy」python0019_ 打包和解包_struct_pack_unpack

作者:oeasy

打包和解包

回憶上次内容

  • ASCII 由這樣幾類字元構成
    • 英文大寫字元
    • 英文小寫字元
    • 數字
    • 符号
  • 電報時代對于英文、數字的編碼
    • 使用的是摩斯電碼
「oeasy」python0019_ 打包和解包_struct_pack_unpack
  • 這摩斯電碼是3進制的編碼方式
    • 長短空
  • 怎麼演化成ascii這種0101的二進制編碼的呢?

回到 ASCII 碼

  • 電報傳過來的信号需要記錄下來
    • 于是有了電傳打字機(tele-typewriter)
    • 電傳打字機需要統一的編碼字母和數字
  • ASCII的第一個商業用途
    • 是作為一個七位電傳打字機(tele-typewriter)代碼
「oeasy」python0019_ 打包和解包_struct_pack_unpack
  • 要把滴、答、停的電報信号
    • 變成0和1的二進制信号

ASCII的演化(evolve)

  • 1960年10月6日
    • 美國标準協會(ASA)X3的首次會議
    • ASCII标準的工作開始了
    • 美國标準協會
      • 現為美國國家标準協會
      • American National Standards Institute
      • 簡稱ANSI
    • 開始敲定ASCII具體編碼
「oeasy」python0019_ 打包和解包_struct_pack_unpack
  • 貝爾公司主要經營電報電話

編碼來源

  • 第一次(ASA X3.4-1963)就明确
    • 大小寫字母之間隻差一個位
    • 這很重要
「oeasy」python0019_ 打包和解包_struct_pack_unpack
  • 否則錯誤編碼一旦成為标準
    • 所有應用這種錯誤編碼的檔案
      • 就都廢掉了
  • 我想把所有 ASCII 字元 0-127 全都打出來
    • 可以麼?

回憶show.py

  • 回憶編寫show.py
for n in range(0xff):
    print(chr(n),end="")
    if n % 16 == 0:
        print()           
  • 确實可以出來
「oeasy」python0019_ 打包和解包_struct_pack_unpack
  • 這輸出靠的是
    • 把序号轉化成字元的函數
      • chr
  • 但是沒有看到0
    • 理論上在1之前
    • 仿佛被黑暗森林所吞沒
  • 我能否将位元組解碼(decode)來幹這個事?

struct

  • 首先是要獲得從0到127的位元組狀态
  • struct 是一個包(module)
    • 導入struct包
「oeasy」python0019_ 打包和解包_struct_pack_unpack
  • struct是結構的意思
    • 來自于c裡面常用類型的存儲結構
    • 這個struct怎麼用呢?

pack

「oeasy」python0019_ 打包和解包_struct_pack_unpack
  • 把數字變成位元組的形态
    • 把0x61這個數字變成位元組的形态
「oeasy」python0019_ 打包和解包_struct_pack_unpack
  • "a" 不是字元嗎?
    • 怎麼成了位元組了?

位元組表示法

  • 注意細節
「oeasy」python0019_ 打包和解包_struct_pack_unpack
  • 注意"a"前面還有一個b
    • "a"是字元
    • b"a" 是位元組
「oeasy」python0019_ 打包和解包_struct_pack_unpack
  • 這兩類型完全不同
  • 位元組b"a"是什麼呢?

位元組形态

  • 位元組狀态可以用兩個16進制數來表示
    • b"a"
      • 相當于b"\x61"
「oeasy」python0019_ 打包和解包_struct_pack_unpack
  • b"a" 和 b"\x61" 是同樣的一個位元組
    • 就是字元"a"在位元組裡的樣子
「oeasy」python0019_ 打包和解包_struct_pack_unpack
  • 為了清楚起見
    • 把b"\x61"表示為b"a"
    • 這樣也就直接看到了字元
    • 剛好ord("a") 就是 0x61
  • 如何了解struct.pack呢?

封包pack

  • 按要求把東西封進規定的封裝裡面
「oeasy」python0019_ 打包和解包_struct_pack_unpack
  • 把數字封在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
  • 可以把數字轉化成位元組狀态
    • 然後可以再把位元組解碼了

周遊結果

  • 好多的位元組呀~
「oeasy」python0019_ 打包和解包_struct_pack_unpack
  • 從位元組狀态可以看到已經有
    • 0、1、2、3
      • 這裡很明顯能看到0
      • 還有0前面的一堆符号
    • A、B、C
    • a、b、c
  • 還有
    • \r、\n、\t
    • 這是啥意思?
    • 怎麼還能有兩個字元呢?
    • 不管他
  • 先加上換行

換行

「oeasy」python0019_ 打包和解包_struct_pack_unpack
  • 從0數到7
    • 換1行
    • 再從0數到7
「oeasy」python0019_ 打包和解包_struct_pack_unpack
  • 隐約看到了ascii碼的結構
    • 我不想看位元組狀态呢
      • 我想看字元狀态
  • 需要對位元組狀态解碼(decode)
    • 也就是解包
      • struct.unpack

解包

  • 這又是一圈
    • pack
    • unpack
「oeasy」python0019_ 打包和解包_struct_pack_unpack
  • 解包出來是序号
  • 先把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

封包再解碼

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
  • 和原來chr方法得到的結果差不多
  • 但是沒有看到字元0
    • 仿佛被上面那片黑暗森林所吞沒
    • 這可真可怕!
  • 我們先去總結一下吧

總結

  • struct包可以讓我們使用封包格式
    • 把數字封包到位元組裡
      • pack函數就是封包
      • unpack函數就是解封
    • 我們通過封到不同位元組的數字
      • 周遊了一次ascii碼
「oeasy」python0019_ 打包和解包_struct_pack_unpack
  • 還是有那片黑色的區域
    • 好像是一片黑暗森林!
    • 那裡面到底有些什麼秘密?
  • 我們下次向黑暗森林區域進發!!
  • 去準備行裝吧
  • 藍橋->https://www.lanqiao.cn/teacher/3584
  • github->https://github.com/overmind1980/oeasy-python-tutorial
  • gitee->https://gitee.com/overmind1980/oeasypython
  • 視訊->https://www.bilibili.com/video/BV1CU4y1Z7gQ 作者:oeasy