编码是怎么回事?

我们通过文字进行人与人间的沟通交流, 对计算机而言只能看得懂01二进制数, 因此,需要将人能看懂的文字, 编码(encode)成机器能看懂的二进制数

ASCII码 和 Unicode编码

先说说ASCII码, Unicode编码

ASCII码用于编码英文字符, 需要占用一个字节(8位), 其中最高位为0, 总共可表示128个英文字符

因为英文字符不多,所以一个字节可以表示所有的英文字符, 但是其他语言如中文, 远不止256个字符, 所以需要一种编码方式,指定每个字符(中文字符/英文字符/其他语言的字符等)其在计算机中二进制数值

为了解决这个问题, 人们规定了Unicode编码, 他是一种编码规范, 给全世界的所有的字符规定一个二进制值, 这样,计算机就能读懂,这些字符

Unicode 编码有以下几个特点?

  • 每个字符的二进制值的字节数可能不同

编码规范是给出来的,但是要怎么实现?

因为每个字符的二进制值的字节数可能不同, 如果全部采用最大二进制的字节数来存储,则会造成存储空间的极大浪费, 因此, 对于这个规范也有许多种实现,比如UTF-8,UTF-16,UTF-32

UTF-8

UTF-8是Unicode 的实现方式之一, 它是最通用的编码方式,因为Unicode规范是定长的, 所以如果存为文本文件,存在占用空间过大问题, 因此一般都需要将字符利用UTF-8等encode方式, 节省空间存储.

UTF-8的主要特定如下:

  • 采用不定长二进制字节表示字符(它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。)

UTF-8是如何实现不定长编码区分所有字符的呢?

  • 对于可用一个字节表示的字符, 字节的第一位设置为0, 后7位与unicode码相同, 所有英文的UTF-8编码与ASCII码相同
  • 对于n字节表示的字符, 从高位开始, 1的个数表示该二进制编码的字节数(第n+1位设为0), 其后每个字节都以10开头, 剩下没有提及的二进制位都是可编码位
1
2
3
4
5
6
# *号表示编码的二进制数
Unicode 符号范围(16进制)| UTF-8 编码方式(二进制) | 可编码位数
0000 0000-0000 007F | 0*** **** | 7
0000 0080-0000 07FF | 110* **** 10** **** | 11
0000 0800-0000 FFFF | 1110 **** 10** **** 10** **** | 16
0001 0000-0010 FFFF | 1111 0*** 10** **** 10** **** 10** **** | 21

的 Unicode 是4E25(01001110 00100101) 总共有16个编码位(根据字节数向上取整,不够的高位补0), 因此需要采用第三行的编码方式1110 0100 1011 1000 1010 0101, 转成二进制就是E4B8A5

因此, Unicode的二进制编码与UTF-8的编码实际上值是不一样的(不定长字节编码, 需要加标识位来识别不同位编码的字符)

Python 的字符类型

python2 str 字符类型 unicode 字符类型
Python2的字符串默认存储为str类型 str类型的二进制值是通过UTF-8等编码得到的二进制值 它的值是根据unicode规范生成的, 即它的二进制值可以通过查看Unicode表得到
Python3 bytes类型 str类型
Python3的字符串默认存储为str类型 str 类型字符串经过encode(UTF-8,ASCII)后变为bytes类型 它的值是根据unicode规范生成的, 即它的二进制值可以通过查看Unicode表得到
1
2
3
4
5
6
7
8
9
Python 2.7.15 (default, May  1 2018, 16:44:37) 
In[2]: b = '严'
In[3]: b
Out[3]: '\xe4\xb8\xa5'
type(b)
Out[4]: str

In[5]: b.decode('utf-8')
Out[5]: u'\u4e25'

由上面可以看出, b 类型是str, 编码方式是UTF-8, 其编码的16进制值为e4b8a5

对b进行UTF-8解码后,得到的结果是Unicode编码值4e25, 该值为unicode类型

1
2
3
4
5
In[6]:  b = u'严' 
In[7]: b
Out[7]: u'\u4e25'
In[8]: type(b)
Out[8]: unicode

我的理解是,默认python2的对字符的默认编码方式是ASCII编码(因此为了避免当py文件中出现中文导致编码报错, 需要增加一行注释来告诉Python使用UTF-8进行编码),得到的二进制值是str类型, 而unicode类型的值是根据unicode编码规范得到的二进制值

Since Python 3.0, the language features a str type that contain Unicode characters, meaning any string created using "unicode rocks!", 'unicode rocks!', or the triple-quoted string syntax is stored as Unicode.

The default encoding for Python source code is UTF-8, so you can simply include a Unicode character in a string literal:

Python3的源码的默认编码是UTF-8, 代码中的字符串(读到内存中)的值是以Unicode形式存储, 因此其是支持非英文字符的

[]: https://docs.python.org/3/howto/unicode.html “Python’s Unicode Support”
[]: http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html “字符编码笔记:ASCII,Unicode 和 UTF-8”
[]: https://www.programiz.com/python-programming/methods/string/encode

本文标题:编码是怎么回事?

文章作者:定。

发布时间:2019年2月19日 - 23时02分

本文字数:2,095字

原始链接:http://cocofe.cn/2019/02/19/python-character-encoding/

许可协议: Attribution-NonCommercial 4.0

转载请保留以上信息。