计算机编码起源与发展

计算机编码起源与发展

本篇主要讲解常见字符编码:

ASCII编码

GB2312编码

GBK编码、GB18030

UNICODE编码

乱码问题及解决方法

 ASCII编码

 ASCII 编码:使用1个字节(8位)来表示一个字符,一共规定了128个字符的编码。
• 0~31及127(共33个)是控制字符或通信专用字符(其余为可显示字符)。
• 32~126(共95个)是字符(32是空格),其中48~57为0到9十个阿拉伯数字。
• 65~90为26个大写英文字母,97~122号为26个小写英文字母,其余为一些标点符号、运算符号等。

• ISO-8859-1:在 ASCII 码基础上,对 10000000(128) ~11111111(255)这一段进行了编码。

 

GB2312编码

使用2个字节表示一个汉字,具体的方式是前127个字符不变。当第一个字节(高字节)大于160的时候,表示一个汉字的开始,再用这个字节组合第二个字节(低字节,范围也是160-255)共同表示一个汉字。
• 在这套编码方式中,不仅把中文编码进去,还把一些数学符号、罗马希腊字母和日本假名等等都编码进去。并且还把ASCII中原有的26个英文字母和符号都编入,当然这些字母是以2个字节表示。

• 为了和ASCII中原有的字母区别表示,称前者为“全角字符”,后者为“半角字符”。

 GB2312其对所收录字符进行了“分区”处理,共94个区,区从1(十进制)开始,一直到94(十进制),每区含有94个位,位从1(十进制)开始,一直到94(十进制),共8836(94 * 94)个码位,这种表示方式也称为区位码,GB2312是双字节编码,其中高字节表示区,低字节表示位。
• 各区具体说明如下:
• 01-09区收录除汉字外的682个字符,有164个空位(9 * 94- 682)。
• 10-15区为空白区,没有使用。
• 16-55区收录3755个一级汉字(简体),按拼音排序。
• 56-87区收录3008个二级汉字(简体),按部首/笔画排序。
• 88-94区为空白区,没有使用。

• 举例来说,“啊”字是GB2312编码中的第一个汉字,它位于16区的01位,所以它的区位码就是1601。

那么根据区位码如何算出GBK2312编码呢?区位码的表示范围为0101 - 9494(包含了空的区位码)。之后只需要按照如下规则进行转化即可。
• 1. 将区(十进制)转化为十六进制。
• 2. 将转化的十六进制加上A0,得到GB2312编码的高字节。
• 3. 将位(十进制)转化为十六进制。
• 4. 将转化的十六进制加上A0,得到GB2312编码的低字节。
• 5. 组合区和位,区在高字节,位在低字节。

• 6. 得到GB2312编码。

具体的流程图如下:

例如:
'李'字的区位码为3278(表示在32区,78位)。
1.将32(区)转化为十六进制为20。
2.加上A0为C0。
3. 将78(位)转化为十六进制为4E。
4. 加上A0为EE。
5. 组合区和位,为C0EE。
6. 得到GB2312编码,即'李'字的GB2312编码为C0EE。

GBK 编码、GB18030

 GBK编码:是在GB2312-80标准基础上的内码扩展规范,使用了双字节编码方案,其编码范围从8140至FEFE(剔除xx7F),首字节在 81-FE 之间,尾字节在 40-FE 之间,共23940个码位,共收录了21003个汉字,完全兼容GB2312-80标准。
• GB18030:后来少数民族也要用电脑了,于是我们再扩展,又加了几千个新的少数民族的字,GBK 扩成了 GB18030。但是没有形成主流,故不做介绍。

UNICODE编码

为了使国际间信息交流更加方便,国际组织制定了UNICODE 字符集,为各种语言中的每一个字符设定了统一并且唯一的数字编号,以满足跨语言、跨平台进行文本转换、处理的要求。
• Unicode字符集包含了各种语言中使用到的所有“字符”。用来给 UNICODE 字符集编码的标准有很多种,比如:UTF-8, UTF-7, UTF-16, UnicodeLittle,UnicodeBig 等。

 

UTF16编码

 

 使用2个字节(16位)或4个字节来存储其编号
• 对于 ascii 里的那些”半角”字符,UNICODE 包持其原编码不变,只是将其长度由原来的8位扩展为16位。而其他文化和语言的字符则全部重新统一编码。
代码点
Unicode标准的本意很简单:希望给世界上每一种文字系统的每一个字符,都分配一个唯一的整数,这些整数叫做代码点 代码点(Code Points)。
代码空间

所有的代码点构成一个代码空间 代码空间(Code Space),根据Unicode定义,总共有1,114,112个代码点,编号从0x0到0x10FFFF。换句话说,如果每个代码点都能够代表一个有效字符的话,Unicode标准最多能够编码1,114,112,也就是大概110多万 多万个字符。

代码平面
Unicode标准把代码点分成了17个 代码平面(Code Plane),编号为#0到#16。每个代码平面包含65,536(2^16)个代码点(17*65,536=1,114,112)。
其中,Plane#0叫做基本多语言平面(Basic MultilingualPlane,BMP),其余平面叫做补充平面(Supplementary Planes)。如下图所示:

BMP代码平面

 BMP是最重要的一个代码平面,大部分常用的字符都定义在这个平面内,如下图所示:

在BMP中定义的代码点包括:
ASCII ASCII总共有128个字符,占据了BMP的前128个代码点(上图绿线)ISO-8859-1 共256个字符,占据了BMP的前256个代码点(上图绿线+蓝线)CJK Unified Ideographs 上图的红色区域(占据BMP大约1/3)定义了两万多个汉字。
Surrogate Code Points 从0xD800到0xDBFF的1024个代码点是High-surrogate代码点,简称高代理。

从0xDC00到0xDFFF的1024个代码点是Low-surrogate代码点,简称低代理。一个High-surrogate代码点和一个Low-surrogate代码点组成一个代理对(Surrogate Pair),可以在UTF-16里编码BMP之外的某个代码点(1024^2+65,536=1,114,112)。

• 举例说明
• 字符 ,其Unicode码点为65902(十进制),十六进制为1016E,很显然,已经超出了第一平面(BMP)所能表示的范围。其在辅助平面内,根据规则,UTF-16采用4个字节进行编码。
• ① 使用Unicode码位减去10000(十六进制),得到的值扩展20位,得到的结果为0016E(十六进制)。
• ② 将步骤一得到值,按照高十位和低十位进行分割,得到016E(低十位),0000(高十位)。
• ③ 将步骤二的高十位再加上D800(十六进制),得到高位代理,值为D800。
• ④ 将步骤二的低十位,再加上DC00(十六进制),得到低位代理,值为DD6E。

• ⑤合并高位代理和低位代理,得到4个字节的UTF16编码,即为D800 DD6E。

UTF8编码

• 对于欧美的一些国家,常用的还是英文字母,使用UTF16,白白浪费一倍的存储空间(因为他们只需前128的字符就足够了)。
• 针对此,UTF8产生了,它是一种变长编码方式,使用8位来实现Unicode中的所有字符。
• 具体如何实现呢?

• 程序将一个字节一个字节的来读取,然后再根据每个字节中开头的标志来识别是该把一个还是两个或三个字节做为一个字符来处理。

UTF8编码规则如下:

• 举例说明
• 字符'A'的Unicode码点为65(十进制),根据上表,在第一行范围,则字符'A'的UTF-8编码为01000001

• 中文字符'李'的Unicode码点为26446(十进制),二进制为01100111 01001110,十六进制为674E。根据上表,在第三行范围,则将'李'二进制代码从低位到高位依次填入x中,不足的填入0。得到UTF-8编码为11100110 10011101 10001110,即E69D8E(十六进制)。

乱码问题

•  为什么会出现乱码
• 简单的说乱码的出现是因为:编码和解码时用了不同或者不兼容的字符集。

• 在计算机科学中一样,一个用UTF-8 编码后的字符,用GBK去 解码。由于两个字符集的字库表不一样,同一个汉字在两个字符表的位置也不同,最终就会出现乱码。  我们来看一个例子:

假设我们用UTF-8 编码存储“很屌”  两个字,会有如下转换:

解码后我们就得到了”寰堝睂”这么一个错误的结果,更要命的是连字符个数都变了。

• GET方式的乱码:

• 如,

<a href=”/demo5/servlet/RD2?name=中国”>CN</a>

 

直接用request.getParameter得到的字符串strCN将会乱码,这也是因为GET方式是用http的url传过来的默认用iso-8859-1编码的,所以首先得到的strCn要再用iso-8859-1编码得到原文后,再进行用utf-8(看具体页面的charset是什么utf-8或gbk)进行解码即可。

 

new String(strCn.getBytes(“ISO-8859-1”),“UTF-8”);

• POST方式的乱码:只需要request.setCharacterEncoding("UTF-8"):即可。

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值