Python 字符集编码 - UTF-8 编码

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python 字符集编码 - UTF-8 编码相关的知识,希望对你有一定的参考价值。

参考技术A

Unicode 的编码范围为 0~0x10FFFF ,如此大的范围,显然没办法像 ASCII 编码一样使用一个字节存储。为此,Unicode 制定了各种储存编码的方式,如: UTF-8 、 UTF-16 和 UTF-32 ,这些存储格式被称为 Unicode 转换格式 UTF 。

每种 Unicode 转换格式都会把一个编码存储为一到多个编码单元,如 UTF-8 的编码单元为 8 位的字节; UTF-16 的编码单元为 16 位,即 2 个字节; UTF-32 的编码单元为 32 位,即 4 个字节。

其中, UTF-8 是在互联网上使用最广泛的一种 Unicode 转换格式,具有以下显著的优势。下面,我们就先来看看 UTF-8 具有哪些有点吧~

1. UTF-8 中每个 ASCII 字符只需要一个字节去存储,因此一个 ASCII 文本本身也是一个 UTF-8 文本,即做到了向后兼容。

比如 A 的 ASCII 码对应为 0x41 , a 的 ASCII 码对应为 0x61 ,那么 UTF-8 兼容 ASCII 也就意味着:

这里,需要再次提醒一下:Unicode 是表现形式,UTF-8 是存储形式;即 UTF-8 解码之后为 Unicode ,Unicode 可以编码成 UTF-8 。

2. UTF-8 采用字节为存储单元,因此不存在字节的大端和小段的问题。

UTF-16 和 UTF-32 的存储单元分别是 2 字节和 4 字节,因此在存储时会涉及到大小端的问题。那什么是大小端模式呢?下面我们来暂停补充一下~

关于如何获知你的环境使用的是大端模式还是小端模式,这里有个简单的方式:定义一个 short 类型的数组即可:

数字 1 在 short 类型中表示为 0x0001 ,高位为 0x00 ,低位为 0x01 。我们可以很直观地看到,数组在保存数据时,将高位 0x00 放在了高地址处,将低位 0x01 放在了低地址处。因此使用的就是小端模式。

那 UTF-8 为什么可以使用字节来作为存储单元,而不用担心字节序的问题呢?这就涉及到了 UTF-8 巧妙的编码规则~

UTF-8 最大的一个特点,就是它是一种变长的编码方式。它可以使用 1~4 个字节表示一个符号,根据不同的符号而变化字节长度。UTF-8的编码规则很简单,只有二条:

1)对于单字节符号,字节的第一位设为 0 ,后 7 位为这个符号的 Unicode 码。也就是我们上文提到的向后兼容:对于英文字母,UTF-8 编码和 ASCII 码是相同的。

2)对于使用 X 个字节存储的符号,第一个字节的前 X 位设置为 1 ,第 X+1 位设置为 0 ,后面字节的前 2 位一律设置为 10 ,剩下的位置一次填充这个符号的 Unicode 码。

下表总结了编码规则,字母 x 表示可用于编码的位:

跟据上表,解读 UTF-8 编码也非常简单:如果一个字节的第一位是 0 ,则这个字节单独就是一个字符;如果第一位是 1 ,则连续有多少个 1 ,就表示当前字符占用多少个字节。

下面,我们就来演示一下 UTF-8 编码的过程。

首先,获取汉字 鱼 的 Unicode 码:

我们不妨先对 鱼 这个汉字使用 utf-8 编码看看使用几个字节存储:

鱼 在 UTF-8 编码中使用 3 个字节存储,因此其存储的二进制的形式为 1110xxxx 10xxxxxx 10xxxxxx ,将 Unicode 1001 110001 111100 依次填充到占位符 x 的位置就得到: 11101001 10110001 10111100 。

下面,我们将上述推导得出的 11101001 10110001 10111100 转换为十六进制,验证一下是否为 b\'\\xe9\\xb1\\xbc\' :

验证无误!

python基础 字符编码转换

python2 

1 #python2上所有的字符编码都需要先decode到unicode,再从unicode encode到目标编码
2 str_utf8 = "我就是我"
3 print("str_utf-8:我就是我:",str_utf8)
4 #将utf-8转换为unicode
5 str_utf8_to_unicode = str_utf8.decode("utf-8")
6 print(str_utf8_to_unicode)
7 #将unicode转换为gbk
8 str_utf8_to_unicode_to_gbk = str_utf8_to_unicode.encode("gbk")

上述程序的print是否能够正常显示和运行终端的编码也有关系

 

python3

字符串与byte类型转换

1 #!/usr/bin/env python
2 # _*_ coding:utf-8 _*_
3 #字符串与二进制的转换只是存储方式的变化,不涉及编码方式的修改,每次encode/decode都需要指定对应字符串的编码格式
4 str1 = "我就是我"
5 #字符串转换为二进制,使用encode。此处编码格式需要与字符串原有编码格式一致,否则在python3上会进行转码操作
6 str1_byte = str1.encode(encoding="utf-8")
7 #二进制转换为字符串,使用decode,此处二进制的编码格式如果填写错误可能会导致二进制无法转换为字符串,导致程序报错
8 byte_str1 = str1_byte.decode(encoding="utf-8")
9 print(str1,str1_byte,byte_str1)

python3上字符编码转换

 1 #!/usr/bin/env python
 2 # _*_ coding:utf-8 _*_
 3 #python3上默认编码是unicode是不需要进行解码这一步,文件头声明-*- coding:gbk -*-只是文件自身的编码,程序里面字符串变量还是unicode,
 4 str2_utf8 = "我就是我"
 5 #python3上str2_utf8默认是unicode编码(字符串本身直接无decode方法),直接encode到对应到编码,同时python3会将其转换为byte类型
 6 str2_utf8_to_gbk = str2_utf8.encode(encoding="gbk")
 7 #打印我就是我的gbk编码byte类型
 8 print(str2_utf8_to_gbk)
 9 #打印我就是我的gbk编码byte类型对应的字符串,只要指定正确的编码类型,也能正确转换为字符串
10 print(str2_utf8_to_gbk.decode(encoding="gbk"))
11 #打印我就是我utf-8编码byte类型,转换byte类型将其encode为自身的utf-8类型即可
12 str2_utf8_to_utf8_byte = str2_utf8.encode(encoding="utf-8")
13 print(str2_utf8_to_utf8_byte)
14 #将我就是我gbk类型转换为utf-8,由于编码转换需要unicode作为中间媒介,先将gbk编码decode至unicode,在将其encode至utf-8;
15 # python在encode是会将其转换为byte类型,所以其输出与str2_utf8_to_utf8_byte打印值一致,如需将其转换为字符串则对其进行自身编码的decode
16 print(str2_utf8_to_gbk.decode(encoding="gbk").encode(encoding="utf-8"))
17 #将二进制的utf-8转换为字符串
18 print(str2_utf8_to_gbk.decode(encoding="gbk").encode(encoding="utf-8").decode("utf-8"))

结果:

b‘xcexd2xbexcdxcaxc7xcexd2‘
我就是我
b‘xe6x88x91xe5xb0xb1xe6x98xafxe6x88x91‘
b‘xe6x88x91xe5xb0xb1xe6x98xafxe6x88x91‘
我就是我

 

划重点:

python3中相比于python的decode除了将原有编码转换为unicode功能外还增加将byte转换为字符串功能;encode除了将unicode转换为对应编码格式外还增加了将字符串转换为byte类型的功能

以上是关于Python 字符集编码 - UTF-8 编码的主要内容,如果未能解决你的问题,请参考以下文章

Python编码

Python 字符编码

拆分给定字节偏移量的 utf-8 编码字符串(python 2.7)

python---字符编码

Python8_关于编码解码和utf-8

转载ASCII,Unicode,UTF-8和python3字符编码