Skip to content

Latest commit

 

History

History
244 lines (170 loc) · 6.27 KB

421-190203-二进制文件流存取整数.sy.md

File metadata and controls

244 lines (170 loc) · 6.27 KB
show version enable_checker
step
1.0
true

二进制文件流存取整数

回忆

  • 上次我们用二进制写了文件
  • 写的时候也可以 seek 调整流文件头
  • 这二进制写(wb)和字符写(wt)好像也差不多
  • 为什么要有这么一个二进制写的方式呢?🤔

写数字

图片描述

  • 尝试直接写数字
  • 失败
  • 需要写的是 bytes-like
    • 字节码形式
  • 那这个时候需要把 123 编码为二进制形式
  • 如何编码呢?

编码

import struct
print(struct.pack('i',123)
  • 这里引入了 struct 包
  • struct 包可以把数字编码
  • 要注意
    • 字节数量
    • 字节序
  • 具体怎么做呢?

具体编码

  • 把 123 编码为 4 字节有符号整型变量
  • "i"
    • 有符号整形变量
    • 代表 4 字节的有符号 integer
  • 编码的结果中有一个大括号这怎么解释?
    • 下图中红框里面的大括号

图片描述

数值验证

图片描述

  • 字符大括号{
    • 对应什么样的字节情况呢?
    • 其实是0x7b
    • b'{\x00\x00\x00'
    • 其实就是
    • b'\x7b\x00\x00\x00'
    • 那么他对应的数字是多少呢?

转化回来

图片描述

图片描述

  • 还真的是可以完全对应上的
  • 那这个可以写到文件里面么?

写入文件

图片描述

  • 写进去了么?
  • 在 terminal 里观察一下

图片描述

  • 真的用二进制形式
    • 或者说 wb的模式 写进去了
  • 那我能再读出来么?

读出

  • rb
    • r - read - 读模式
    • b - binary - 二进制

图片描述

  • 解码之后出来的是一个元组
    • 元组就是一个数字的集合
    • (123,) 这个元组只包含一个元素
    • 就是第 0 个元素
    • 需要用 [0] 得到第 0 个元素

优劣分析

  • 123 用 txt 文本的方式读写
    • 用 4 个字节
    • 运算的话,需要把字符串型转化为 int 型
  • 123 用 binary 二进制方式读写
    • 用 4 个字节
    • 运算的话可以直接运算
  • 但是,二进制方式读写并没有独特的优势啊
  • 我们再来试试

整型数字存储

  • i(每个数字4字节的方式)来读写
    • 4 个数据都是 i
    • 所以数据格式就是i*4
    • 也就是iiii
    • 总共需要 4*4=16 字节

图片描述

  • 第一个数123对应的字节序列是b'{\x00\x00\x00'

图片描述

  • 第二个数1234对应的字节序列是b'\xd2\x04\x00\x00'

图片描述

  • 第三个数12345
    • 对应的字节序列是
    • b'90\x00\x00'
    • 也就是
    • b'\x39\x30\x00\x00'

图片描述

  • 第四个数是123456,可以自行计算
  • 这四个数都是4个字节,共16个字节
  • 用字符串方式存储又会如何呢?

字符串存储

  • 对比纯文本的话
    • 3+4+5+6 = 17 字节

图片描述

  • 而且还要加上 3 个分隔符(\n换行符x)

    • 17 + 3 = 21 字节
    • 最终文本转化为数字也需要开销
  • 更何况二进制存储格式非常多

    • 有符号无符号
    • byte、short、int、long 等
  • 这一批可以写进去么?

写入

  • 写进去

图片描述

  • 好像真的一把写入了 4 个变量共 16 个字节

验证

  • 去文件系统验证

图片描述

  • 可以读出来么?

读取

  • 用二进制读出来

图片描述

  • 读写成功

优点

  • pack 和 unpack
    • 明确地规定了到底用哪种方式进行编码解码
    • 这对于编程是很明确的
  • 原来不同的系统有不同的数据编码方式
  • c 语言 大致规定了 不同数据类型的位数
  • 但是还有些不明确的地方
    • 比如 16 位机 和 32 位机 对于 int 长度
    • 可能加法之后
    • 反而出现负数
  • 这对于早期 python 用户是难以理解的
    • 科学家、数学家
    • 对于补码的概念还是不理解的
    • 包括递归导致的空间不足
    • 堆栈溢出等等
    • 当时确实属于专业领域
  • 他们会因此放弃使用 python
  • 他们需要的是科学计算
  • 而不是成为程序员
  • 所以易用易学是 python 的目标
  • 如果出了问题
    • python 会指出 Error 出在哪
    • 哪个数据什么时候在哪不合适
  • pack、unpack 和 encode、decode 都是编解码
    • 有什么不同呢?

类型不同

  • pack、unpack 一般指的是数字类型的编码和解码

图片描述

  • encode、decode 一般指的是字符串类型的编码和解码

图片描述

  • 那么什么是编码和解码呢?

编码解码

  • pack、unpack 是对于数字型变量的
    • 这里是浮点型数字

图片描述

  • encode 和 decode 是对于字符型变量的

图片描述

  • 编码和解码
    • pack、encode 都是编码
      • 都是把现实世界的数字和文字转化为二进制
    • unpack、decode 都是解码
      • 都是把二进制转化为现实世界的数字和文字

总结

  • 这次在文件流中读写了二进制数字
  • 在多数字的读写实践中,确认
    • 二进制数字更有优势
  • 文件流中可以读写浮点型数字么?🤔
  • 下次再说 👋