Python 编码的一些问题

时间:2022-04-05 15:03:20
# 编码问题
- 为什么需要编码问题
- 本质上计算机只能识别01代码
- 如何用一长串01代码表示复杂信息
- 编码历史
- 二进制
- byte: 一个0或1的二进制
- bit: 8个01代码,字节
- 第一阶段: ASCII
- 第二阶段: 百花齐放, GB2312, GBK, Latin1, Big5, JIS.....
- Latin1: 兼容欧洲大多数语言
- 中国: GBxxxx
- 韩国和*: BIG5
- 日本: JIS
- 微软: ANSI-MBCS(Multi-bytes charecter set,多字节字符集)
- 第三阶段: Unicode(ISO) # 编码表示方法
- ASCII-american standard code for information interchane
- 所有控制字符(包括回车,删除等)编码再0-31范围已经127
- 所有标点符号, 英文大小写在32-126之间
- 预留128-255之间
- 0xxx xxxx 代码的形式
- Latin1
- 0-127之间不动,那么就可以兼容ASCII码,二进制位0xxx xxxx
  - 128-255的范围全部用完,二进制1xxx xxxx
  - 128-159之间控制字符
  - 160-255之间是文字字符
  - 其中包括希腊语,西欧语,泰语,阿拉伯语,希伯来语
  - 欧元符号
- GBxxxxxx
- GB2312
  - 如果一个字节第一位是0,那么他就是ASCII码
  - 如果第一个字节是1,那么他就是汉字,需要2个字节表示一个编码的文字
  - 这个码表中包含汉字6763个和非汉字图像字符682个
  - 0xxxxxxx: 表示ASCII字符
  - 1xxxxxxx xxxxxxxx: 表示汉字
- GBK
- 在GB2312基础上添加汉字
  - 兼容GB2312和ASCII码
  - 0xxxxxxx: 表示ASCII字符
  - 1xxxxxxx xxxxxxxx: 表示汉字
- GB18030
- 2/4位混编码 - Unicode编码问题
- 实例: "中" -> 45629 -> 二进制
- Unicode只是一个码表,具体实现没有规定
- 0-0x10FFFF来映射这些组反映,最多可以容纳1114112字符
- 中文的编码范围4E00-9FCF,其中9FC4-9FCF之间的区间没有使用
- 上述区间全部是汉字,不包含全角字符,不包含特殊文字
- UTF = Unicode Transformation Format
- UTF-8
0X0000~0x007F (0 ~ 127) 1字节 0xxxxxxx
0x0080~0x07FF(128 ~ 2047) 110xxxxx 10xxxxxx
0x0800~FFFF(2048 ~ 65535) 3字节 1110xxxx 10xxxxxx 10xxxxxx
0x10000~1FFFFFF(65536 ~ 2097152) 4字节 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
0x2000000~0x3FFFFFF 5字节 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
0x4000000~0x7FFFFFFF 6字节 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx - UTF-16, UTF-32
- UTF-16 早期历史遗留问题
- UTF-32 浪费空间 - UCS-2
  - USC = UniversalCharacterSet,通用字符集
  - UCS-2与Unicode相同
  - 采用2个字节,定长的表示一个字符,所以总计可以表示2^16个字符
- UCS-4
  - 第一个字节: 表示组(group), 最高位为0, 则有128个
  - 第二个字节: 表示平面(Plane), 256个
  - 第三个字节: 表示行(row), 256个
  - 第四个字节: 表示码位(cell), 256个
  - 如果UCS-4前两个字节为0, 则就是CUS-2 # 常用概念:
- 编码/解码: 由人类可直接读取信息转换成bytes格式的,叫编码,反之叫解码
- 大尾(BigEndian)和小尾(LittleEndian)
- '汉' -> 6C49
  - 6c49 -> BigEndian
  - 496C -> LittleEndian - BOM
- UTF-8: 没有字节顺序问题
  - UTF-16: 会出现问题
- "奎" -> 594E
- "乙" -> 4E59
- BOM-ByteOrderMark
    - "ZERO WIDTH NO-BREAK SPACE" -> FEFF, 在UCS中不存在
    - FEFF -> BigEndian
    - FFFE -> LittleEndian
    - Utf-8 用来表示编码, FEFF的UTF-8编码是 EF BB BF ,用来表示此编码是UTF-8编码 # Python的问题
- str
- bytes
- bytearray
- 编码指定实例:
>>> b = byte.fromhex('E4 B8 AD)
>>> b
b'\xe4\xb8\xad'
>>> b.decode('utf-8')
'中'
>>> str(b)
" b'\\xe4\\xb8\\xa" - 编码和解码的实例:
>>> ord('A')
65
>>> ord('中')
20013
>>> chr(65)
'A'
>>> chr(20013)
'中' - Python文件默认是UTF-8编码,如果需要特殊需要,需要声明
- 放在第一项,或者第二行
- '''# -*- coding: windows-1252 -*-'''
- 读写文件默认UTF-8,可以指定
- code point 方式比较字符串, 可能会带来问题
    - 重音符号的表示
    - 使用 unicodedata.normalize 函数
- Python源码出现了解码错误,那么会产生SyntaxError异常
- 其他情况下,如果发现编码解码错误,那么会产生UnicodeEncodeError,UnicodeDecodeError异常 # 参考资料
- https://blog.csdn.net/xuejianhui/article/details/52576771
- https://www.cnblogs.com/jessonluo/p/4800331.html
- http://tools.jb51.net/table/gb2312