字符串编码和解码

来源:互联网 发布:r语言和python区别 编辑:程序博客网 时间:2024/04/30 14:31

字符串的存储和展示

计算机底层通过二进制存储数据,字符串的存储和展示有这样的关系:

字符串<-->字符<-->二进制存储

在传统的编码方式中,如 ASCII、ISO-8859-1,是直接将字符与二进制数进行了映射,形成一个字符表。这样,存储字符串时,查找字符表,把其中每个字符都用对应的二进制数进行表示。当展示数据时,同样查找字符表,把二进制数转化成对应的字符。

早期通过 ASCII 编码字符串,但随着计算机的发展,需要越来越多的字符要在计算机中进行表示,出现了各种编码方式,如 ISO-8859-1、GBK 等。使用同一种编码不会出现问题,但国际间需要交流,双方可能使用的是不同的编码方式,这样交流时就会出现问题,即 "乱码"。

因此需要一种统一的编码来解决这种问题,就出现了 Unicode。


Unicode

Unicode 在 "字符" 和 "二进制存储" 之间引入了一个抽象层,这样的好处是在可以在不考虑具体的存储时,表示更多的字符。此时字符串的存储和展示有这样的关系:

字符串<-->字符<-->十六进制数描述<-->二进制存储

这个 "十六进制数描述" 即所谓的 code point。它与具体的存储无关,只用来进行字符到数字的映射。对于具体的存储,可以采用各种符合需求的编码方式。
当然可采用 "code point 直接转换成二进制数" 的方式进行存储,但此时有这样的问题:

  • 可移植性问题 (CPU 处理的 字节序 问题)
  • 空间的浪费 (有很多字节都是 0)
  • 与某些编程语言、国际标准不兼容
  • etc.

当然也可以用之前常见的编码方式,如 ASCII、ISO-8859-1 等,但若这些编码中不包含 Unicode 中对应的 code point,则展现的数据可能会是问号或 '-> ' 之类的,出现乱码,因为缺少对应的映射关系。

当前国际上常用的编码是 UTF-8,它解决了上述提到的那些问题。
还有 UTF-16、UTF-32 之类的编码,但由于是多字节的字符表示,会有字节序的问题,即是 "大端存储还是小端存储",此时引入了 Byte Order Mark,通过在文本开头的几个字节表明当前的 UTF-* 编码是哪种字节序。


Python3 中的字符串

Python3 现在对字符串的处理进行了统一和严格规定,把字符串分成两类:

  • text (通过 Unicode 表示,即 str)
  • data (二进制形式,即编码过的 text,存储在存储介质中,即 bytes)

通过上述的描述,可以清楚理解到,str 到 bytes 的转换需要 encode,bytes 到 str 的转换需要 decode。

解释几种场景下字符串的形式:

  • 编辑器中编辑的
    此时都是 str (即 Unicode 形式)。
  • 存储介质读取的
    如打开文件时,若 mode 不指定为 b,则获得是 str,若指定了 b,则获得是 bytes。
  • 网络 IO 获取的
    网络传输的是二进制数,即编码过的字符串,若获得的是原始字符流,则是 bytes,若所使用的库自动进行了 decode,则获得的是 str。
    如 requests 这个网络库,抓取到的网络内容若通过 text 属性查看,是 str 类型,requests 自动进行了 decode。若通过 content 属性查看,则是 bytes 类型,requests 没有进行 decode。可参考 这里。


参考资料

  • Text Vs. Data Instead Of Unicode Vs. 8-bit
  • Unicode HOWTO
  • The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)
  • Character encoding
  • Unicode
  • UTF-8
  • code point
  • 字节序
  • Byte Order Mark
0 0
原创粉丝点击