字符的表示

计算机中最常处理的数据信息除了数值数据外,还有我们人类交流的语言,也就是文字。所谓文字就是一些记录信息的图像符号,也称字符。因此字符信息在计算机中的表示是不可缺少的。然而,不同的国家和民族所使用的字符各不相同,计算机中是如何来表示这些不同的字符呢?

在计算机中是通过字符编码的方式来表示这些字符的。计算机中储存的信息都是用二进制数表示的,而我们在屏幕上看到的英文、汉字字符是二进制转换之后的结果。通俗的说,按照何种规则将字符存储在计算机中,如"a"用什么表示,称为编码;反之,将存储在计算机中的二进制数解析显示出来,称为解码,如同密码学中的加密和解密。在解码过程中,如果使用了错误的解码规则,则导致“a”解析成“b”或者乱码。

所以,字符编码就是一些约定,使用指定的机器整数的集合来表示某个字符集,其中每个机器整数代表一个字符,从而实现字符信息的传递和记录。并且,不同的编码的取值范围不同,所能表示的字符集也有所不同。

ASCII码

ASCII码(American Standard Code for Information Interchange)即美国标准信息码,一种使用7bit或8bit二进制位进行编码的方案。ASCII码于1961年被提出,用于在不同计算机硬件和软件系统中实现数据传输标准化,大多数的小型机和全部的个人计算机都使用此码。该编码后来被国际标准化组织(ISO)采纳而成为一种国际通用的信息交换标准代码,即国际5号码。ASCII码最初采用7bit进行编码,一共有2^7 (128)种编码,从00000000到11111111可以表示128个不同的字符。现扩充为8bit编码,最多可以给256个字符(包括字母、数字、标点符号、控制字符及其他符号)分配或指定数值。所以ASCII码划分为两个集合:128个字符的标准ASCII码和附加的128个字符的扩充ASCII码。

基本的ASCII字符集共有128个字符。对应的ISO标准为ISO646标准。这128个字符又可以分为两类:可显示/打印字符95个和控制字符33个。所谓可显示/打印字符是指包括0~9十个数字符,a~z、A~Z共52个英文字母符号,“+”“-”“≠”“/”等运算符号,“。”“?”“,”“;”等标点符号,“#”“%”等商用符号在内的95个可以通过键盘直接输入的符号,它们都能在屏幕上显示或通过打印机打印出来。控制字符是用来实现数据通信时的传输控制、打印或显示时的格式控制,以及对外部设备的操作控制等特殊功能。这33个控制字符都是不可直接显示或打印(即不可见)的字符。如编码为7F的DEL用作删除操作,编码为07的BEL用作响铃控制等。

其中,字母和数字的ASCII码的记忆是非常简单的。我们只要记住了一个字母或数字的ASCII码(例如记住A的ASCII码为65,0的ASCII码为48),知道相应的大小写字母之间差32,就可以推算出其余字母、数字的ASCII码。

虽然标准的ASCII码是7位编码,但由于计算机基本处理单位为字节(1Byte=8bit),所以一般仍以一个字节来存放一个ASCII字符。每一个字节中多余出来的一位(最高位)在计算机内部通常保持为0(在数据传输时可用作奇偶校验位)。

由于标准ASCII字符集数目有限,在实际应用中往往无法满足要求。为此,ISO又制定了ISO2022标注,它规定了在保持与ISO646兼容的前提下,将ASCII字符集扩充为8位代码的统一方法。ISO陆续制定了一批适用于不同地区的扩充ASCII字符集,每种扩充ASCII字符集分别可以扩充128个字符,这些扩充字符的编码均为高位为1的8位代码(即十进制数128~255),我们称之为扩展ASCII码。

Unicode码

1.Unicode码概述

最初,计算机技术起源和发展主要在欧美发达国家,这使得ASCII码非常流行。ASCII码对英语来说简单实用,但是无法表示其他国家的语言字符。随着计算机实用的普及,ASCII码已经不能满足全世界其它语言国家的需求。于是Unicode编码字符集应运而生。

Unicode码中文名叫万国码,创立之初(1991年)便是希望能够定制一套可以容纳所有文字、符号的集合。最初,Unicode码被设计为16bit的字符编码。Unicode码的基本思路是将每个字符或符号赋予一个永久、唯一的16位值,叫作码点。值得初学者注意的是,最初的Unicode码和ASCII码的第一个区别是Unicode码规定每个字符长度为16位,而ASCII码只有8.这样Unicode码一共能够提供65536个码点,为Unicode码容纳更多语言字符提供了可能,其中就包括了汉字的编码。

然而,这样的16bit的编码所能产生的字符数65536虽然比ASCII码的256有很大的增加,但是还不足以表示世界上所有的字符。因此Unicode码后又进行了扩展,从0开始,一直到0x10FFFF(以“ox”开头的数代表使用十六进制计数)共1114112个数字。每一数字映射一个符号。现在把[0,0x10FFFF]这个大区段等分成17个小区段,每个区段有65536个数字。这些区段就叫作平面,共有17个平面。然而目前只用了少数平面。

Unicode码平面分步
平面始末字符值中文名称英文名称
0号平面0x0000~0xFFFF基本多文种平面Basic Multilingual Plane,简称BMP
1号平面0x10000~0x1FFFF多文种补充平面Supplementary Multilingual Plane,简称SMP
2号平面0x20000~0x2FFFF表意文字补充平面Supplementary Ideographic Place,简称 SIP
3号平面0x30000~0x3FFFF表意文字第三平面(未正式使用)Tertiary Ideographic Place,简称TIP
4号平面至13号平面0x40000~0xDFFFF(尚未使用) 
14号平面0xE0000~0xEFFFF特别用途补充平面Supplementary Special-purpose plane,简称SSP
15号平面0xF0000~0xFFFFF保留作为私人使用区(A区)Private Use Area-A,简称 PUA-A
16号平面0x100000~0x10FFFF保留作为私人使用区(B区)Private Use Area-B,简称 PUA-B

 

在Unicode5.0.0版本中,已定义的码位只有238605个,分布在平面0、平面1、平面2、平面14、平面15、平面16上。其中平面15和平面16上只是定义了两个各占65534个码位的专用区(Private Use Area),分别是0xF0000~0xFFFFD和0x100000~0x10FFFD.所谓专用区,就是保留给大家放自定义的区域,可以简写为PUA。

平面0也有一个专用区:0xE00~0xF8FF,有6400个码位。平面0的0xD800~0xDFFF,共2048个码位,是一个呗称作代理区(Surrogate)的特殊区域。用于和UTF-16之间的转换,该部分内容在下面讲述UTF-16的时候会详细介绍。

如前所述在Unicode 5.0.0版本中,238605-65534*2-6400-2048=99089,余下的99089个已定义码位分步在平面0、平面1、平面2和平面14上,它们对应着Unicode定义的99089个字符,其中包括71226个汉字。平面0、平面1、平面2和平面14上分别定义了52080、3419、43253和337个字符,平面2上的43253个字符都是汉字,平面0上定义了27973个汉字。

比如,在Unicode中,汉字“字”对应的数字是23383(十进制),十六进制表示为0x5B57.在Unicode中,我们有很多方式将数字23383表示成程序中的数据,包括:UTF-8、UTF-16、UTF-32.UTF是“Unicode Transformation Format”的缩写,可以翻译成Unicode字符集转换格式,即怎样将Unicode定义的数字转换成程序数据。

事实上,现在的计算机中的字符和字符串,并不是直接以Unicode码存储的,而是使用上述UTF-8、UTF-16、UTF-32三种方式进行转换后再存储。原因是直接使用Unicode码会导致较严重的效率问题。举例说明:

Unicode的最小编码是+0x00.而最大值是+0x10FFFF,长度不确定。所以在计算机存储的时候,就需要确定多少位表示一个符号。比如说字符串“a中”,它的Unicode码是0x00614E2D,换算成二进制就是0000 0000 0110 0001 0100 1110 0010 1101,假设我们采用16位(2Byte)表示一个Unicode符号,那么在计算机中,符号a就要存储成“0000 0000 0110 0001”,这样的情况中文还好,但是英文就会浪费存储空间。尤其当数据需要在网络上传输或者需要压缩、数据库处理的时候都需要越小存储体积越好的,所以当前计算机中不直接存储Unicode码。

2.编码实现方式

(1)UTF-8编码

UTF-8以字节为单位对Unicode进行编码。从Unicode到UTF-8的编码方式如下所示。

Unicode到UTF-8编码方式
Unicode编码(十六进制)UTF-8字节流(二进制)占用字节数
00000000-0000007F0xxxxxxx1
00000080-000007FF110xxxxx 10xxxxxx2
00000800-0000FFFF1110xxxx 10xxxxxx 10xxxxxx3
00010000-001FFFFF11110xxx 10xxxxxx 10xxxxxx10xxxxxx4
00200000-03FFFFFF111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx5
04000000-7FFFFFFF1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx6

 

编码规则为:对于单字节符号,UTF-8编码首位为0,其余各位填充Unicode码即可;对于n字节符号,UTF-8编码首字节前n位全为1,第n+1为0,其余各字节前两位为10,余下的位置填充Unicode码即可。目前,UTF-8编码长度最大为4个字节,所以最多只能表示Unicode编码值的二进制位数为21位的Unicode字符。但是已经能表示当前所有的Unicode字符,因为Unicode的最大码位0x10FFFF也只有21位。5字节和6字节UTF-8属于UCS-4的扩展内容。

UTF-8的特点是:它是一个可变长度的字符编码。对于0x00~0x7F之间的字符,UTF-8编码与ASCII编码完全相同。UTF-8编码的最大长度是6个字节,字符所占用的内存空间大小为1个字节到6个字节不等。从上表可以看出,6字节模板有31个“x”,既可以容纳31位二进制数字。Unicode的最大码位0x7FFFFFFF也只有31位。

例如,“汉”字的Unicode编码是0x6C49.0x6C49在0x0800~0xFFFF之间,使用3字节模板:1110xxxx 10xxxxxx 10xxxxxx.将0x6C49 写成二进制是:0110 1100 0100 1001,用这个比特流依次代替模板中的“x”,得到:11100110 10110001 10001001,即0xE6B189.

(2)UTF-16编码

UTF-16编码以16位无符号整数为单位。Unicode字符的码位需要一个或者两个十六位二进制数来表示。因此UTF-16也是一个可变长度的字符编码。我们把Unicode编码记作U,编码规则如下:

①如果U<0x10000,U的UTF-16编码就是U对应的16位无符号整数。

②如果U>=0x10000,我们先计算U=U-0x10000,然后将U写成二进制形式:yyyy yyyy yyxx xxxx xxxx,U的UTF-16编码二进制形式就是:110110yyyyyyyyyy 110111xxxxxxxxxx.

从Unicode到UTF-16的编码方式如下所示。

Unicode到UTF-16编码方式
十六进制编码范围十进制码范围UTF-16表示方法(二进制)字节数量
0x0000~0xFFFF0~65535xxxxxxxx xxxxxxxx2
0x10000~0x10FFFF65536~1114111110110yyyyyyyyyy 110111xxxxxxxxxx4

 

为什么U可以被写成20个二进制位?Unicode的最大码位是0x10FFFF,减去0x10000后,U的最大值是0xFFFFF,所以肯定可以用20个二进制位表示。

例如,Unicode编码0x20C30,减去0x10000后,得到0x10C30,写成二进制是:0001 0000 1100 0011 0000.用前10位依次替代模板中的x,就得到二进制编码:1101100001000011 1101110000110000,即0xD843 0xDC30.

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mez_Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值