字符编码
文本编辑器与Python解释器原理
# 文本文件内容全都为字符,无论存取都涉及到字符编码问题,如果使用的是ascii编码
#1、存文本文件
人类通过文本编辑器输入的字符会被转化成ASCII格式的二进制存放于内存中,如果需要永久保存,则直接将内存中的ASCII格式的二进制写入硬盘
#2、读文本文件
直接将硬盘中的ASCII格式的二进制读入内存,然后通过ASCII表反解成对应字符
# 如果使用的是 gbk编码
# 存文本文件
那么人类通过文本编辑器输入的字符会被转化成GBK格式的二进制存放于内存中,如果需要永久保存,则直接将内存中的GBK格式的二进制写入硬盘
#2、读文本文件
直接将硬盘中的GBK格式的二进制读入内存,然后通过GBK表反解成对应字符
发展历史
1. ASCII表的诞生:由于现代计算机起源于美国,最初只考虑让计算机识别英文字符,因此诞生了ASCII表。
ASCII表的特点:
ASCII表中只有英文字符与数字的一一对应关系。每个英文字符对应1字节(8位),最多可以表示256个字符,足够覆盖所有英文字符。
字母对应ASCII表:
大写字母A-Z对应的ASCII值为65-90,
小写字母a-z对应的ASCII值为97-122,
数字0-9对应的ASCII值为48-57。
同时,小写字母对应的ASCII值一定大于大写字母的ASCII值。
2. 但是我要知道这个世界是需要交流的,按照目前的编码条件,国家之间是不能通过计算机通信的,因为每个国家的编码都不一样,这样的结果会导致字符显示乱码的问题。
1. GBK表的特点:
- GBK表是中国人为了让计算机能够识别中文和英文而定制的字符编码表。
- GBK表中只有中文字符、英文字符和数字的一一对应关系。
- 一个英文字符对应1字节,一个中文字符对应2字节。
2. 各国不同的编码表:
- 日本为了识别日文字符和英文字符与数字的一一对应关系,定制了Shift_JIS表。
- 韩国为了识别韩文字符和英文字符与数字的一一对应关系,定制了Euc-kr表。
- 美国使用ASCII作为字符编码标准,中国使用GBK,日本使用Shift_JIS。
3. 多种编码共存的缺点:
- 目前的字符编码表(ASCII、GBK、Shift_JIS)无法识别万国字符。
- 这导致在不同国家的计算机上,只能输入对应字符编码表支持的字符,无法输入其他国家的字符。
- 为了解决这个问题,需要定制一个兼容万国字符的编码表。
- Unicode的特点:
- Unicode于1990年开始研发,1994年正式公布。
- Unicode存在所有语言中的所有字符与数字的一一对应关系,即兼容万国字符。
- 与传统的字符编码的二进制数都有对应关系。
- Unicode的第二个特点是为了解决旧系统和应用软件采用各种传统编码的问题。
- 为了让计算机能够正常运行这些传统编码的软件而不出现乱码,内存中必须有一种兼容万国字符的编码,并且该编码需要与其他编码有相应的映射/转换关系。
- 字符的存储:
- 在文本编辑器中输入的任何字符都以Unicode编码存在于内存中。
- 存放于硬盘中的字符可以转换成任意其他编码,只要该编码支持相应的字符。
- 英文字符可以被ASCII识别,转换过程为英文字符 → Unicode格式的数字 → ASCII格式的数字。
- 中文字符和英文字符可以被GBK识别,转换过程为中文字符、英文字符 → Unicode格式的数字 → GBK格式的数字。
- 日文字符和英文字符可以被Shift-JIS识别,转换过程为日文字符、英文字符 → Unicode格式的数字 → Shift-JIS格式的数字。
- unicode的缺点
- 内存占用太大
ASCII表
1、只支持英文字符串
2、采用8位二进制对应一个英文字符串
ASCII表的特点:
1、只有英文字符与数字的一一对应关系
2、一个英文字符对应1Bytes,1Bytes=8bit,8bit最多包含256个数字,可以对应256个字符,足够表示所有英文字符
GBK表
- 支持英文字符、中文字符
- 采用8位(8Bit=1Bytes)二进制对应一个英文字符串
- 采用16位(16Bit=2Bytes)二进制对应一个中文字符串
GBK表的特点:
1、只有中文字符、英文字符与数字的一一对应关系
2、一个英文字符对应1Bytes 一个中文字符对应2Bytes
Unicode
很多地方或老的系统、应用软件仍会采用各种各样传统的编码,这是历史遗留问题。
此处需要强调:软件是存放于硬盘的,而运行软件是要将软件加载到内存的;
面对硬盘中存放的各种传统编码的软件,想让我们的计算机能够将它们全都正常运行而不出现乱码,内存中必须有一种兼容万国的编码,并且该编码需要与其他编码有相对应的映射/转换关系,这就是unicode第二大特点产生的缘由
注意:内存中统一使用Unicode(文本编辑器输入任何字符在内存中都是Unicode编码的)
- 兼容万国字符,与万国字符编码都有对应关系
- 采用16位(16Bit=2Bytes)二进制数对应一个中文字符串,个别生僻字会采用4Bytes,8Bytes
# 英文字符可以被ASCII识别
英文字符--->unciode格式的二进制--->ASCII格式的二进制
# 中文字符、英文字符可以被GBK识别
中文字符、英文字符--->unicode格式的二进制--->gbk格式的二进制
# 日文字符、英文字符可以被shift-JIS识别
日文字符、英文字符--->unicode格式的二进制--->shift-JIS格式的二进制
Unicode表
内存
字符---------------------Unicode格式的数字-----------------
| |
| |
| |
硬 盘 |
| |
| |
| |
GBK格式的二进制 Shit-JIS格式的二进制
老的字符编码都可以转成Unicode,单不能通过Unicode互转
UTF-8
Unicode解决了万国字符和二进制的对应关系,但是使用Unicode表示一个字符,太浪费空间。例如:利用Unicode表示“Python”需要12个字节才能表示,比原来ASCII表示增加了1倍。
由于计算机的内存比较大,并且字符串在内容中表示时也不会特别大,所以内容可以使用Unicode来处理,但是存储和网络传输时一般数据都会非常多,那么增加1倍将是无法容忍的!!!
为了解决存储和网络传输的问题,出现了Unicode Transformation Format,学术名UTF,即:对Unicode中的进行转换,以便于在存储和网络传输时可以节省空间!
- UTF-8: 使用1、2、3、4个字节表示所有字符;优先使用1个字符、无法满足则使增加一个字节,最多4个字节。英文占1个字节、欧洲语系占2个、东亚占3个,其它及特殊字符占4个。
- UTF-16: 使用2、4个字节表示所有字符;优先使用2个字节,否则使用4个字节表示。
- UTF-32: 使用4个字节表示所有字符。
那为何在内存中不直接使用utf-8呢?
utf-8是不定长的:一个英文字符占1Bytes,一个中文字符占3Bytes,生僻字用更多的Bytes存储
# 原因1:
也就意味着如果用户输入的字符是:你y好,在内存中需要先经历计算的过程:“你”应该用3Bytes,“y”应该用1Bytes,“好”应该用3Bytes,然后才能存储,所以内存中如果直接使用utf-8格式去存储字符,耗费的总时间=计算时间+存储时间,而内存中使用定长的unicode格式存储字符,就省去了计算时间,所以内存中使用unicode来存储字符会浪费空间,但是会提升速度,这是一种用空间换时间的方法
# 原因2:
历史遗留问题,硬盘中存在很多其他编码方式的文件,内存如果此时使用utf8就会导致乱码问题
总结:UTF 是为Unicode编码 设计 的一种 在存储 和传输时节省空间的编码方案。
UTF-8
- 英文 ----》 1Bytes
- 汉字 ----》 3Bytes
结论
-
内存固定使用Unicode,我们可以改变的是存入硬盘采用格式
英文 + 汉字 ----》 Unicode ----》 gbk 英文 + 日文 ----》 Unicode ----》 shift-jis 万国字符 ----》 Unicode ----》 utf-8
-
文本文件存取乱码问题
存乱了:解决方法是,编码格式应该设置成支持文件内容字符串的格式
取乱了:解决方法是,文件是以什么编码格式存入硬盘的,就应该以什么编码格式读入内存。
-
python默认读文件的编码:
python3
默认utf-8
python2
默认ASCII
指定文件编码
在
py
文件的首行写、只需要在主文件加文件头。# coding:utf-8 (按当初存入的编码为准)
-
保存运行python程序的前两个阶段不乱码的核心法则
指定文件头
# coding:文件当初存入硬盘时所采用的编码格式
-
python3
的str
类型默认直接存成Unicode
格式,无论如何都不会乱码保存
python2
的str
类型不乱码x = u'上'
在字符串前面加一个u
强制转成Unicode -
了解
python2
解释器有两种字符串类型:str
以及Unicode
# str类型 x = '上' # 字符串值会按照文件头指定的编码格式存入变量值的内存空间 # Unicode类型 x = u'上' # 强制存成Unicode
编码:Unicode 转成 其他编码
解码:其他编码转成 Unicode
用什么去编码,就要用什么去解码,推荐用
utf-8
去编码和解码x = '上' res = x.decode('gbk') # Unicode编码成gbk print(res, type(res)) >>> b'\xc9\xcf' <class 'bytes'> text = res.decode('gbk') print(text) >>> 上
-
默认编码
pycharm
默认的终端编码是utf-8
- mac的终端默认也是
utf-8
win10 cmd
的终端默认是GBK
最后再提示一下,Python只要出现各种编码问题,无非是哪里的编码设置出错了
常见编码错误的原因有:
- Python解释器的默认编码
- Python源文件文件编码
- Terminal使用的编码
- 操作系统的语言设置
本文作者:小满三岁啦
本文链接:https://www.cnblogs.com/ccsvip/p/17874880.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。