字符编码相关知识总结

1. 什么是字符

字符是书写的最基本构建单元。字符可以表示字母、数字、标点、表意符号(比如汉字)、数学符号,或者其他的书写基本单元。

不能把字符和字形相混淆。字符是唯一的,抽象的语言“原子”。字形是画出每个符号时使用的特定方式。只有当用一种字形替代另一种字形,文本的意思发生了改变,才把这些字形看成是不同的字符。否则,这些字形就是同一个字符的不同风格的表示形式。

 

比如上图中的九个字形,虽然形状各异,但一看就知道是小写字母a,所以这九个字形代表的是小写字母a这同一个字符。

2. 编码后的字符集(coded character set

编码后的字符集将整数映射到字符。编码后的字符集经常用数组来实现,通过代码数值来进行索引。数组的元素就是字符。下面举例说明一些常见的编码后字符集。

1) US-ASCII

ASCII表示“美国标准信息交换代码”(American Standard Code for Information Interchange)。ASCII是最著名的编码后字符集,早在1968年就由ANSI进行了标准化。ASCII的代码值范围是0到127(用十六进制表示是0x00到0x7F),因此只需7个二进制码就可以覆盖整个代码空间。ASCII的推荐名称是US-ASCII,这样可以和那些7位字符集的一些国际化变体进行区分。HTTP报文(首部、URI等)使用的字符集是US-ASCII。

 

2) iso-8859

iso-8859字符集标准是US-ASCII的8位超集,使用二进制码的高位增加了一些国际化书面字符。有额外的二进制码增加的空间(多了128个代码,从0x80到0xFF)还不够大,甚至还不够所有的欧洲字符使用,更不用说亚洲字符了。因此iso-8859为不同地区定制了不同的字符集。其中最著名的就是iso-8859-1,用于表示西欧语言(英语、法语等)。iso-8859-1的别名是Latin1,是HTML的默认字符集。

3) UCS

UCS(Universal Character Set)把全世界的所有字符都整合到了单一的编码后字符集中。UCS由ISO 10646定义。Unicode是遵循UCS标准的商业化联合组织。

在UCS标准中,代码空间被分成了17个平面(planes),每个平面有65536(2的16次方)个代码点(code points),所以总共有1,114,112个代码点。这个数字很奇怪,因为它不是2的幂。这其实是UTF-16编码方案的设计所造成的结果。

在UTF-16中,用两个代码单元(共四个字节)组成的“代理对”(surrogate pair)来编码1到16平面中的2^20个代码点(2^4个平面乘以每个平面2^16个代码点),而对0平面进行编码只需要一个代码单元(两个字节)。2^20 + 2^16 = 1024^2 + 65536 = 1114112。

 

UCS中的第一个平面,0平面,也叫“基本多语种平面”(Basic Multilingual Plane,BMP)。这个平面是到目前为止大部分字符所在的地方。而BMP中的大部分代码点都被用于对中日韩的字符进行编码。上图中浅灰色区域中,0xD800到0xDFFF(8 * 2^8 = 2^11 = 2048)这个区域(倒数第三行后半部分)不对应任何字符,而是被保留用于在UTF-16编码方案中对代理对进行编码。

3. 字符编码方案(character encoding scheme

字符编码方案(character encoding scheme)和编码后的字符集(coded character set)不是一个概念。字符集给所包含的每个字符分配一个整数编号,而编码方案规定如何把字符的代码数字打包装入二进制的比特数据中,以及如何在另一端将其解包回字符代码。

 

字符编码方案主要有以下3种类型。

固定宽度

固定宽度方式的编码用固定数量的比特表示每个编码后的字符。它们能被快速处理,但可能会浪费空间。

可变宽度

可变宽度方式的编码对不同的字符代码数字采用不同数量的比特。对于常用字符,这样可以减少所需的位数,而且还能在允许使用多字节来表示国际性字符的同时,保持对传统8位字符集的兼容性。

可变宽度(有模态)

有模态的编码使用特殊的“转义”模式在不同的模态之间进行切换。例如,可以用有模态的编码在文本中使用多个互相重叠的字符集。有模态的编码处理起来比较复杂,但可以有效地支持复杂的书写系统。

1) 8位编码

iso-8859字符集家族系列使用的是8位的恒等编码。这种编码把每个字符代码直接编码为相应的8位二进制数值。这种编码方式只支持代码范围包含256个字符的字符集。

2) UTF-8

UTF-8是一种流行的为UCS设计的字符编码方案,UTF表示UCS变换格式(UCS Transformation Format)。UTF-8为字符代码值使用的是无模态的变宽编码。第一个字节的高位表示编码后字符所用的字节数,后续每个字节都固定包含6位的代码值。

 

如果编码后的第一个字节的最高位是0,则编码长度就是一个字节,剩余的7位就包含字符的代码。这样一来就美妙地达到了与ASCII的兼容(但和iso-8856系列不兼容)。

例如字符代码90(ASCII的“Z”)在0到127的范围内,故只需一个字节进行编码(90 = 64 + 16 + 8 + 2 = 2^6 + 2^4 + 2^3 + 2,编码为0,101,1010)。而代码5073需要13位二进制数(1,001111,010001),会被编码为3个字节(见上图第三行):

11100001  10001111  1001001

注意UTF-8的最大编码值是31位,能编码2^31个代码值,这远远大于UCS的代码范围(相当于2^15,即32768个平面)。

3) UTF-16

UTF-16编码方案能够对UCS中的1,112,064个代码点进行编码(1,114,112减去从U+D800到U+DFFF这2048个用于代理对的代码点)。UTF-16编码长度要么是两个字节(对于从U+0000到U+D7FF,以及从U+E000到U+FFFF的基本平面代码点),要么是4个字节(对于从U+1,0000到U+10,FFFF的16个辅助平面中的代码点)。

辅助平面中的代码点长度超过两个字节,用两个16位的代码单元(称为一个代理对)来进行编码,具体编码方式如下:

  • 将代码点的值减去0x1,0000,得到一个20比特的范围在0到0xFFFFF之间的数。(辅助平面本身有16 * 2^16 = 2^20个代码点。)
  • 20个比特中的头10个比特(0到0x3FF之间的数)与0xD800相加,得到第一个代码单元或者叫高位代理(lead surrogate),该值在0xD800到0xDBFF之间。
  • 低位的10个比特(值同样在0到0x3FF之间)与0xDC00相加,得到第二个代码单元,或者叫低位代理(trail surrogate),取值范围是0xDC00到0xDFFF。

从这里就能看出为什么要保留0xD800到0xDFFF这个范围了,因为0xDFFF – 0xD800 + 1等于0x800,等于2 * 2^10,即切成两半,每一半可以代理表示2^10个数,组合起来正好可以代理表示2^20个辅助平面中的代码点(2^10 * 2^10 = 2^20)。

思考一下为什么要用代理对来进行编码,而不是用4个字节直接表示辅助平面中代码点的值?

转载于:https://www.cnblogs.com/lihaiyang/archive/2013/03/16/2963631.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值