ASCII和Unicode编码详解

来源:互联网 发布:初中数学答题软件 编辑:程序博客网 时间:2024/05/29 16:05

本文参考大量维基百科和网络大牛的文章,并结合实际例子,试图帮助大家理清计算机的编码问题,从而更加高效的编写程序。

一.    知识补充

1.1  位

我们常说的位是指比特位,即bit,每一个bit位存储一个0或者1。所以,在计算机(二进制数系统)中,一个位(bit)就是指一个0或者1。我们说计算机的CPU一次能处理的最大位数就是指这个位。

1.2  字节

字节(Byte)是指一小组相邻的二进制数码,每8个位组成一个字节,即1Byte = 8bit。我们通俗的说,8个0或者1组成一个字节。字节是计算机基本的信息存储和处理单位。

二.    ASCII

ASCII是由美国制定的标准单字节字符编码方案,主要用于显示现代英语。标准ASCII码使用7位二进制数来表示所有的大写和小写字母、数字0~9、标点符号和特殊控制字符,共计128个字符,具体可以参照ASCII对照表查看。

在标准的ASCII中,最高位(b7)用作奇偶校验位。奇校验规定:正确的代码一个字节中1的个数必须是奇数,若非奇数,则在最高位b7添1;偶校验道理相似。

由于标准ASCII字符集字符数目有限,无法满足需求,国际标准组织在兼容的前提下,将ASCII字符集扩充为8位代码的统一方法,后面补充的这128个字符编码就称为扩展ASCII码。

三.    Unicode

Unicode和UCS的详细区别请google。

前面说到8位ASCII远远不能满足所有字符的编码需求,怎么办?增加二进制表示的位数。最初版本的unicode字符编码采用16位,这样就能表示65536个码位,此版本也称UCS2。这对于表示世界上大多数的语言、字符已经是充裕的了。

但是为什么说只是充裕的?因为这些组织在制定这些字符集的时候就想了,如果有一天,外星人来到地球,并带来了新的语言或符号,或者我们人类进化,某个种族突然创造出一种新的语言怎么办?好吧,在16位的基础上再加16位,现在32位,够了吧?这就是UCS-4版本,UCS-4是一个更大的32位字符集,最高位恒为0,可以表示2^31个字符,这样足够了,但是实际并非如此。

在UCS4中,所有的编码空间被分为17个平面,每个平面包含2^16个码位。第一个平面称为基本多语言平面(BMP),也称第0平面,与我们现在实际中用的UCS-2编码相同,BMP使用16位的编码空间,码位从U+0000到U+FFFF,包含了我们常用的字符。

到这里,我们已经把全世界有的没有的语言、符号都赋予了一个唯一的二进制码位。似乎是没问题了,但是美国不同意了,为什么?因为我们前面说美国制定的ASCII编码,只用一个字节就能表示他们用到的所有大小写字母、字符等,为什么要换成占用两个字节unicode?而且高字节的八个位都是0,这样对存储空间和传输空间都是浪费。为了解决这个这个问题,UCS字符U+0000到U+007F被编码为字节0X00到0X7F,只占用1个字节,这样unicode便与ASCII兼容了。

下面我们举例演示unicode编码:

A  à  \u41

朕 à   \u6715

字母A的unicode编码是\u41,1个字节,转换二进制是 0100 0001,和A的ASCII码一致。

中文“朕”的unicode编码是\u6715,2个字节,转换二进制是

01100111 0001 0101,

unicode的工作是制定了类似“朕”与0110 0111 0001 0101之间唯一的映射。

四.    Unicode实现方式UTF

Unicode是一个字符集,收录的字符和编码是唯一对应的,它只规定了如何编码,并没有规定如何保存、传输这个编码。所以我们说unicode只完成了一半的工作,还需要定义一种方法来确定码位在内存和硬盘中如何表示,unicode标准为此定义了几种映射,称为unicode转换格式,简称UTF。

1.      UTF-32

我们首先介绍UTF-32,UTF-32是最清楚的,但是使用最少的一个。为何?每一个码位使用整32位,因此每一个UTF-32值都可以直接表示对应的码位。然而,UTF-32几乎从来没在实际中使用过,因为每个字符占用4个字节,这样就太浪费空间了。

2.      UTF-16

前面我们说到Unicode编码空间被划分为17个平面,每个平面包括65536个码位。第一个平面称为基本多语言平面,简称BMP,其它平面称为辅助平面。

在BMP中,从U+D800到U+DFFF之间的码位区段是永久保留不映射的字符,UTF-16就是利用保留下来的这个区段码位来映射辅助平面的字符的码位。

3.      UTF-8

UTF-8使用1-6个字节为每个字符编码:

一个字节编码128个ASCII字符(U+0000---U+007F);

二个字节编码拉丁文等附带符号的其它字符(U+0080---U+07FF);

三个字节编码BMP中的其它字符,包括中文;

四~六个字节编码unicode辅助平面的字符。

UTF-8的编码规则:

1)单字节符号,最高位为0,后面7位为这个符号的unicode码,因此一个字符表示的UTF-8编码与对应的ASCII码是相同的;

2)N(N>1)字节符号,最高字节的前N位全为1、第N+1位为0,后面字节的前两位为10,所有字节剩余的位,由符号的unicode码补充。

下面举例演示UTF-8的编码规则:

a)       中文“朕”是BMP中的字符,编码为UTF-8使用3 个字符,根据UTF-8的编码规则2,首先我们我三字节的框架搭好: 

1110xxxx 10xxxxxx 10xxxxxx

b)       查到朕的十六进制unicode编码是\u6715,转换为二进制代码是

01100111 00010101

c)       将这串二进制代码填充空余处(如颜色示意):

01100111 00010101

1110xxxx 10xxxxxx 10xxxxxx

11100110 10011100 10010101

d)       将上述的二进制字符串转换为16进制就是

\xe6\x9c\x95

五.     中文编码

1.      GB2312字符集

GB2312是中国规定的汉字编码,也可以说是简体中文的字符集编码,共收录6763个汉字和682个字符,每个汉字及符号以两个字节来表示

2.      GBK

GBK是GB2312的扩展,除了兼容GB2312外,还收录了中文繁体、日语中的一些字符。

六.    混淆点

1.      UTF不是一种编码,只是unicode编码的一种储存和传送格式

Unicode\GBK\GB2312是编码字符集

2.      UTF-8码完全针对unicode,如果GBK要转为UTF-8,必须先转为unicode码,然后才能转为UTF-8,反之一样。

 

七.    Python的编码问题

1.      python 2.x编码问题根源

Python2.x版本编写的程序默认采用ASCII编码,这个通过sys模块便能直接看到看到。

       Import sys

       Print sys.getdefaultencodeing()

根据上面我们对ASCII的编码格式分析,ASCII只能识别包含大小写英文字母、特殊字符个标点符号在内的128个字符,那么问题就来了,如果在我们的代码中使用了某些个超出ASCII编码范围的字符,比如中文,python解释器就不能识别这个特殊的字符,所以会报出了如下的错误:

UnicodeDecodeError:'ascii' codec can't decode byte 0x?? in position x: ordinal not in range(128)

初期python使用者最常见的一个异常,其根本原因就在于此。

 

 

0 0
原创粉丝点击