Python基础入门第四课--字符编码
这一节本来是和上一节的变量、函数写在一起的,由于是基础入门,写的太多会理解不了,所以将这部分分开来阐述。这里主要说字符编码的相关问题。
1.字符编码
在C语言中,我们学到最基础最重要的概念莫过于字符串了,那也是我们经常碰见的一个类型,我们在编程中会常常使用,在掌握一个类型的使用和方法以前,了解一下它的发展过程还是很有必要的。
- ASCII码
ASCII第一次以规范标准的类型发表是在1967年,最后一次更新则是在1986年,至今为止共定义了128个字符;其中33个字符无法显示(一些终端提供了扩展,使得这些字符可显示为诸如笑脸、扑克牌花式等8-bit符号),且这33个字符多数都已是陈废的控制字符。控制字符的用途主要是用来操控已经处理过的文字。在33个字符之外的是95个可显示的字符。用键盘敲下空白键所产生的空白字符也算1个可显示字符(显示为空白)。
USASCII code chart:
但是存在一些问题:那个时候计算机还只是拉丁文字的专利,根本没有想到现在计算机的发展势头,如果想到了,可能一开始就会使用unicode了。当时绝大部分专家都认为,要用计算机,必须熟练掌握英文。这种编码占用7个Bit,在计算机中占用一个字节,8位,最高位没用,通讯的时候有时用作奇偶校验位。因此ASCII编码的取值范围实际上是:0x00-0x7f,只能表示128个字符。后来发现128个不太够用,做了扩展,叫做ASCII扩展编码,用足八位,取值范围变成:0x00-0xff,能表示256个字符。其实这种扩展意义不大,因为256个字符表示一些非拉丁文字远远不够,但是表示拉丁文字,又用不完。所以扩展的意义还是为了下面的ANSI编码服务。
- ANSI
美国国家标准协会,也就是说,每个国家(非拉丁语系国家)自己制定自己的文字的编码规则,并得到了ANSI认可,符合ANSI的标准,全世界在表示对应国家文字的时候都通用这种编码就叫ANSI编码。换句话说,中国的ANSI编码和在日本的ANSI的意思是不一样的,因为都代表自己国家的文字编码标准。比如中国的ANSI对应就是GB2312标准,日本就是JIT标准,香港,台湾对应的是BIG5标准等等。
那么到底ANSI是多少位呢?这个不一定!比如在GB2312和GBK,BIG5中,是两位!但是其他标准或者其他语言如果不够用,就完全可能不止两位!
例如:GB18030:
GB18030-2000(GBK2K)在GBK的基础上进一步扩展了汉字,增加了藏、蒙等少数民族的字形。GBK2K从根本上解决了字位不够,字形不足的问题。它有几个特点:它并没有确定所有的字形,只是规定了编码范围,留待以后扩充。
编码是变长的,其二字节部分与GBK兼容;四字节部分是扩充的字形、字位,其编码范围是首字节0x81-0xfe、二字节0x30-0x39、三字节0x81-0xfe、四字节0x30-0x39。它的推广是分阶段的,首先要求实现的是能够完全映射到Unicode3.0标准的所有字形。它是国家标准,是强制性的。
搞懂了ANSI的含义,我们发现ANSI有个致命的缺陷,就是每个标准是各自为阵的,不保证能兼容。换句话说,要同时显示中文和日本文或者阿拉伯文,就完全可能会出现一个编码两个字符集里面都有对应,不知道该显示哪一个的问题,也就是编码重叠的问题。显然这样的方案不好,所以Unicode才会出现!
- MBCS
计算机的发展速度是很快的,ASCII这种单字节的编码已经满足不了需求了。在计算机中也存在许多的其他语言,每个语言就自己制定了一套属于自己的编码,从而就出现了我们称为支持多字节字符集(MBCS)的字符集编码方法。
多字节字符系统或者字符集,基于ANSI编码的原理上,对一个字符的表示实际上无法确定他需要占用几个字节的,只能从编码本身来区分和解释。因此计算机在存储的时候,就是采用多字节存储的形式。也就是你需要几个字节我给你放几个字节,比如A我给你放一个字节,比如”中“,我就给你放两个字节,这样的字符表示形式就是MBCS。
在基于GBK的windows中,不会超过2个字节,所以windows这种表示形式有叫做DBCS(Double-Byte Chactacter System),其实算是MBCS的一个特例。 C语言默认存放字符串就是用的MBCS格式。从原理上来说,这样是非常经济的一种方式。
- Unicode
这是一个编码方案,说白了就是一张包含全世界所有文字的一个编码表,不管你用的上,用不上,不管是现在用的,还是以前用过的,只要这个世界上存在的文字符号,统统给你一个唯一的编码,这样就不可能有任何冲突了。不管你要同时显示任何文字,都没有问题。
因此在这样的方案下,Unicode出现了。Unicode编码范围是:0-0x10FFFF,可以容纳1114112个字符,100多万啊。全世界的字符根本用不完了,Unicode 5.0版本中,才用了238605个码位。所以足够了。
因此从码位范围看,严格的unicode需要3个字节来存储。但是考虑到理解性和计算机处理的方便性,理论上还是用4个字节来描述。
Unicode采用的汉字相关编码用的是《CJK统一汉字编码字符集》— 国家标准 GB13000.1 是完全等同于国际标准《通用多八位编码字符集 (UCS)》 ISO 10646.1。《GB13000.1》中最重要的也经常被采用的是其双字节形式的基本多文种平面。在这65536个码位的空间中,定义了几乎所有国家或地区的语言文字和符号。其中从0x4E00到 0x9FA5 的连续
区域包含了 20902 个来自中国(包括台湾)、日本、韩国的汉字,称为 CJK (Chinese Japanese Korean) 汉字。CJK是《GB2312-80》、《BIG5》等字符集的超集。
CJK包含了中国,日本,韩国,越南,香港,也就是CJKVH。这个在UNICODE的Charset chart中可以明显看到。 unicode的相关标准可以从unicode.org上面获得,目前已经进行到了6.0版本。
Unicode的实现方案:
Unicode其实只是一张巨大的编码表。要在计算机里面实现,也出现了几种不同的方案。也就是说如何表示unicode编码的问题。
(1)UTF-8(UCS Transformation Format 8bit)
这个方案的意思以8位为单位来标识文字,注意并不是说一个文字用8位标识。他其实是一种MBCS方案,可变字节的。到底需要几个字节表示一个符号,这个要根据这个符号的unicode编码来决定,最多4个字节。
编码规则如下:
Unicode编码(16进制) ║ UTF-8 字节流(二进制)
000000 - 00007F ║ 0xxxxxxx
000080 - 0007FF ║ 110xxxxx 10xxxxxx
000800 - 00FFFF ║ 1110xxxx 10xxxxxx 10xxxxxx
010000 - 10FFFF ║ 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
UTF-8的特点是对不同范围的字符使用不同长度的编码。对于0x00-0x7F之间的字符,UTF-8编码与ASCII编码完全相同。
UTF-8编码的最大长度是4个字节。从上表可以看出,4字节模板有21个x,即可以容纳21位二进制数字。Unicode的最大码位0x10FFFF也只有21位。
例1:“汉”字的Unicode编码是0x6C49。0x6C49在0x0800-0xFFFF之间,使用用3字节模板了:1110xxxx 10xxxxxx 10xxxxxx。将0x6C49写成二进制是:0110 1100 0100 1001, 用这个比特流依次代替模板中的x,得到:11100110 10110001 10001001,即E6 B1 89。
例2:Unicode编码0x20C30在0x010000-0x10FFFF之间,使用用4字节模板了:11110xxx 10xxxxxx 10xxxxxx 10xxxxxx。
将0x20C30写成21位二进制数字(不足21位就在前面补0):0 0010 0000 1100 0011 0000,用这个比特流依次代替模板中的x,得到:11110000 10100000 10110000 10110000,即F0 A0 B0 B0。
(2)UTF-16
UTF-16编码以16位无符号整数为单位。注意是16位为一个单位,不表示一个字符就只有16位。现在机器上的unicode编码一般指的就是UTF-16。绝大部分2个字节就够了,但是不能绝对的说所有字符都是2个字节。这个要看字符的unicode编码处于什么范围而定,有可能是2个字节,也可能是4个字节。这点请注意!
下面算法解释来自百度百科。
我们把Unicode unicode编码记作U。编码规则如下:
如果U<0x10000,U的UTF-16编码就是U对应的16位无符号整数(为书写简便,下文将16位无符号整数记作WORD)。
如果U≥0x10000,我们先计算U’=U-0x10000,然后将U’写成二进制形式:yyyy yyyy yyxx xxxx xxxx,U的UTF-16编码(二进制)就是:110110yyyyyyyyyy 110111xxxxxxxxxx。为什么U’可以被写成20个二进制位?Unicode的最大码位是0x10ffff,减去0x10000后,U’的最大值是0xfffff,所以肯定可以用20个二进制位表示。
例如:Unicode编码0x20C30,减去0x10000后,得到0x10C30,写成二进制是:0001 0000 1100 0011 0000。用前10位依次替代模板中的y,用后10位依次替代模板中的x,就得到:1101100001000011 1101110000110000,即0xD843 0xDC30。
按照上述规则,Unicode编码0x10000-0x10FFFF的UTF-16编码有两个WORD,第一个WORD的高6位是110110,第二个WORD的高6位是110111。可见,第一个WORD的取值范围(二进制)是11011000 00000000到11011011 11111111,即0xD800-0xDBFF。第二个WORD的取值范围(二进制)是11011100 00000000到11011111 11111111,即0xDC00-0xDFFF。
为了将一个WORD的UTF-16编码与两个WORD的UTF-16编码区分开来,Unicode编码的设计者将0xD800-0xDFFF保留下来,并称为代理区(Surrogate):
D800-DB7F ║ High Surrogates ║ 高位替代
DB80-DBFF ║ High Private Use Surrogates ║ 高位专用替代
DC00-DFFF ║ Low Surrogates ║ 低位替代
高位替代就是指这个范围的码位是两个WORD的UTF-16编码的第一个WORD。低位替代就是指这个范围的码位是两个WORD的UTF-16编码的第二个WORD。那么,高位专用替代是什么意思?我们来解答这个问题,顺便看看怎么由UTF-16编码推导Unicode编码。
如果一个字符的UTF-16编码的第一个WORD在0xDB80到0xDBFF之间,那么它的Unicode编码在什么范围内?我们知道第二个WORD的取值范围是0xDC00-0xDFFF,所以这个字符的UTF-16编码范围应该是0xDB80 0xDC00到0xDBFF 0xDFFF。我们将这个范围写成二进制: 1101101110000000 11011100 00000000 - 1101101111111111 1101111111111111 按照编码的相反步骤,取出高低WORD的后10位,并拼在一起,得到 1110 0000 0000 0000 0000 - 1111 1111 1111 1111 1111
即0xe0000-0xfffff,按照编码的相反步骤再加上0x10000,得到0xf0000-0x10ffff。这就是UTF-16编码的第一个WORD在0xdb80到0xdbff之间的Unicode编码范围,即平面15和平面16。因为Unicode标准将平面15和平面16都作为专用区,所以0xDB80到0xDBFF之间的保留码位被称作高位专用替代。
(3)UTF-32
这个就简单了,和Unicode码表基本一一对应,固定四个字节。
为什么不采用UTF-32呢,因为unicode定义的范围太大了,其实99%的人使用的字符编码不会超过2个字节,所以如同统一用4个字节,简单倒是简单了,但是数据冗余确实太大了,不好,所以16位是最好的。就算遇到超过16位能表示的字符,我们也可以通过上面讲到的代理技术,采用32位标识,这样的方案是最好的。所以现在绝大部分机器实现unicode还是采用的utf-16的方案。当然也有UTF-8的方案。比如windows用的就是UTF16方案,不少linux用的就是utf8方案。
(来源:CSDN ASCII、ANSI、MBCS、UNICODE字符集详解)
2.Unicode和UTF-8有何差异
Unicode符号范围 | UTF-8编码方式
(十六进制) | (二进制)
—————————————————————–
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
(来源:知乎 Unicode和UTF-8有何区别)
3.Python 2.x中编码问题
Python2和Python3里面的编码还是有些区别的,此处课参考下面两篇文章,可以得到详细的解答。
博客园 python字符编码详解
CSDN Python2和Python3之间关于字符串编码处理的差别
这部分就先说这么多,下一章节预告:模块
Python基础入门第四课--字符编码相关推荐
- python海龟图画龙珠_阿里云天池龙珠计划——Python基础入门第2课:变量和赋值...
阿里云天池龙珠计划--Python基础入门第2课:变量和赋值 [我是测试题2]下面这段代码的运行结果是什么? # 运行一下结果就出来了 a = "hello" b = " ...
- 韩语学习之——基础入门第四课辅音
一 概念 辅音分类: 送气音 紧音 二 送气音 2.1 不送气音 No 韩语 汉语发音 1 ㄱ 可(ke) 2 ㄷ 特(te) 3 ㅂ 破(po) 4 ㅈ 次(ci) 2.2 送气音 No 韩语 汉语 ...
- C#编程入门第四课,异常,switch-case选择结构,循环结构 while,break作用,do-while循环
C#编程入门第四课 文章目录 C#编程入门第四课 1.异常 2. switch- case选择结构 3. 循环结构 while 4. break 作用 5. do-while循环 1.异常 那行代码有 ...
- Node.js基础入门第四天
经过前面三天的学习,Node.js的基础知识已逐渐掌握,今天继续学习缓存区和文件操作,并稍加整理加以分享,如有不足之处,还请指正. 缓存区 1. 什么是缓存区? JavaScript语言自身只有基本数 ...
- python基础入门第0天
一.python的起源 python是一门 解释型弱类型编程语言. 另外还有一个选择python 的理由是后面自己可能会自学一些人工智能,机器学习等内容,也算是先打打基础吧. 特点: 简单.明确.优雅 ...
- mbedtls 入门第四课--移植mbedtls到VS和ESP8266--8266SDK SHA256移植
承接上篇,我们初步了解了mbedtls的文件路径以及文件作用以后就是想着如何将mbedtls移植到各种平台. 博主这里只有两种移植方法,第一是将代码移植到VS中,第二个是将代码移植到博主跑动的比较多的 ...
- Flash鼠绘入门第四课:绘制漂亮的梅花
本课教学内容与目的:通过学习画梅花进一步掌握 flash 软件中线条工具.椭圆工具.混色器.变形面版.填充变形工具的使用. 一.先观看一下梅花的形态,建立梅花色形的感性认识. [img]/upload ...
- python基础笔记第四课_字典集合笔记
一.可变与不可变类型: 1.不可变类型:定义好变量后,不能修改.添加.删除 int .float. tuple. bool. str 都为不可变类型 2.可变类型:定义好变量后,可进行修改内部元素 l ...
- Flash鼠绘入门第四课:绘制漂亮的梅花-梅花照片分析与学习
一.先观看一下梅花的形态,建立梅花色形的感性认识. 梅花照片1 梅花照片2 梅花照片3 打开 flash 软件建一文档并保存为<梅花>,属性默认. 一.新建图形元件-梅花1 1.把图层1改 ...
最新文章
- [Nginx优化]分享nginx配置文件及优化说明
- 2020-12-4((ARM汇编)mov指令,LDR指令,LDR伪指令)
- Struts2中使用OGNL表达式投影(过滤)集合
- 30几岁该有多少存款才算合格?
- 电脑中毒的表现有哪些?电脑中毒了怎么办?
- 移动端导出excel_连载系列【4】Excel开发移动端quot;APPquot;
- linux通过rpm和yum安装包
- MATLAB-基本简介
- 叮铃铃~: 一个Vue铃声/提示音组件
- 视频教程-网页设计速成之Dreamweaver-Dreamweaver
- 【Java前端】CSS(一)[字体,文本属性,调试工具]
- 苹果硅之后:PC市场会走向何方?
- 2023 《电脑PC游戏》 红警3:起义时刻
- ansys_lsdyna输出.k文件lsprepost输出部件加速度
- json学习笔记(圣思园视频学习笔记)
- tar 将软连接的文件也进行打包
- StatusBarUtil 状态栏工具类(实现沉浸式状态栏/变色状态栏)
- Tailwind教程2 - 基础样式
- (四)Substance Painter贴图制作软件的使用
- 南开大学计算机考研大纲,南开大学2019年考研812计算机综合基础考试大纲