字符集和字符编码

来源:互联网 发布:淘宝贷款逾期最坏结果 编辑:程序博客网 时间:2024/06/16 22:56

在一个测量的程序中遇到了乱码问题,因此特意了解了一些字符编码的知识。

本文对unicode、UCS、UCS-2、UCS-4、UTF-8、UTF-16、UTF-32等容易混淆的概念阐述了自己一些粗浅的理解,欢迎大家批评指正。


首先要了解一下什么是“字符集”和“字符编码”。


根据百度百科的定义,字符“是各种文字和符号的总称”,一个英文字母、一个汉字,一个阿拉伯数字、一个逗号甚至一个箭头符号都可以算是一个字符。

字符集是指“多个字符的集合”,是人为定义的、囊括了不同范围的字符的集合。{‘a’,'b','c'}就是一个字符集,十个阿拉伯数字也可以组成一个字符集,所有的大小写英文字母加上十个阿拉伯数字就构成了一个更大一些的字符集。

字符编码是对应于字符集的一个概念,计算机不能直接存储字符,只能存储二进制数字,因此有必要制定一定的对应关系,将某个字符集中的每一个字符映射为一定长度的二进制数字,这种字符集中的每个字符到二进制数据的对应关系就称为字符编码。

不同的计算机之间由二进制数据进行通信,这就要求互相通信的计算机之间制定一个字符集到其二进制编码的固定标准,否则接受者将无法“读懂”发送者所发送的信息。


ASCII编码是计算机诞生早期使用最广泛的一种字符集及其编码标准,其全称为American Standard Code for Information Interchange,译为美国信息交换标准代码。这里所说的ASCII标准同时囊括了“ASCII字符集”和“ASCII字符编码”两个概念。标准ASCII码使用7位二进制数表示128种字符:所有的大写和小写字母、数字0到9、标点符号,以及在美式英语中使用的特殊控制字符。如图所示


标准ASCII编码所用的7位二进制数在计算机中通常使用一个字节来存储(最高位置0),经过扩充的ASCII编码可以使用8个字节来表示256个字符,满足了早期以英语为母语的国家的计算机互相通讯的需要。


随着计算机的普及,计算机越来越需要使用多国语言文字,ASCII的256个字符在非英语国家显得不够用了。各国纷纷制定自己国家的字符集及其编码标准,1980年中国颁布了GB2312标准(《信息交换用汉字编码字符集·基本集》),包含了6763个汉字字符和682个非汉字图形字符(也包括英文字母和数字等),用一个字节存储这么多的字符显然是不够的,于是GB2312标准使用两个字节来存储一个字符。其中第一个字节称为“区码”,第二个字节称为“位码”,区码和位码的取值范围都在1-94之间,因此也称为“区位码”。

为了兼容标准ASCII的128个字符,将表示汉字的两个字节的最高位分别置为1(标准ASCII码的单字节最高位为0),这样计算机就可以识别每个字节是ASCII编码的西文字符还是由两个字节组成的GB2312编码的中文字符。然而这并不是区位码在计算机中真正的存储形式,实际存储时还要对每个字节进行一些转化,具体的转化形式称为EUC(Extended Unix Code)—CN字符编码。

为了对生僻汉字的扩展(GB2312标准不包括某些人名、古汉语等方面出现的罕用字等),1995年中国又颁布了GBK标准(《汉字编码扩展规范》),这一标准实际上是对GB2312的扩充,仍然使用两个字节表示汉字,向下完全兼容GB2312和ASCII。

这里还要提到一种BIG5(大五码)编码标准,也就是繁体汉字字符集及其编码,它流行于香港台湾一代,弥补了GB2312没有繁体汉字字符的缺点,用两个字节存储。

以上的字符编码标准,都同时包括了“字符集”和“字符编码”。


上述的GB2312等标准是中国的标准,它们支持中文和拉丁文字的双语处理,其实每个国家也有自己的不同标准,但大多只支持拉丁文字及其本国语言的双语处理,因此在同一个软件中要实现多种语言处理时(例如同时需要中文、英文、日文、德文),各国传统的编码标准便不能做到。另外,每个国家使用不同的编码标准,当在一个国家的系统中打开另一个国家的文件时,就会出现乱码现象。

如果有一种编码,将世界上所有的符号都纳入其中,无论是英文、日文、还是中文等,大家都使用这个编码表,就不会出现编码不匹配现象。

凑巧的是,两种这样的通用编码:Unicode和UCS,分别由不同的组织开发出来了。


Unicode(统一码、万国码、单一码)由Unicode组织开发,它是一个巨大的字符集,基本囊括了世界各地的语言字符。任何文字在Unicode中都对应一个值,这个值称为代码点(code point)。代码点的值通常写成 U+ABCD 的格式。代码点只是一个字符的编号,并不是该字符在计算机中存储的真实二进制代码,这一点与ascii、GB2312、GBK、BIG5等标准是不同的。Unicode只规定了字符及其对应的编号,但没有规定字符在计算机中存储的形式。

规定Unicode存储方式的编码标准称为UTF(Unicode Transformation Format),包括UTF-8、UTF-16和UTF-32等等。
UTF-16使用两个字节来表示一个unicode代码点,UTF-32使用四个字节来表示一个unicode代码点。
UTF-16的两个字节不足以表示所有Unicode字符,只能牺牲一些不常用的字符,并且UTF-16和UTF-32的一个缺点就是它们固定使用两个或四个字节,这样在表示纯ASCII文件时会有很多00字节,造成资源浪费和效率低下。
UTF-8是一种可变长度编码,由Ken Thompson于1992年创建。用1到6个字节编码Unicode字符。ASCII字符用1个字节表示,与其ASCII码完全相同,比较常用的字符编码成2-3个字节,靠后的生僻字可能编码成4-6个字节,整体的编码效率得以提升。

ISO组织也开发了一套巨大的字符集(ISO10646项目),名字叫“ Universal Multiple-Octet Coded Character Set”(通用字符集),简称UCS。UCS基本包含了用于表达所有已知语言的字符。


后来,双方意识到世界上不需要2套通用的字符集,所以双方开始进行整合。

UCS也根据Unicode的代码点给了每个字符的对应编号:UCS-2(2字节存储Unicode代码点U+ABCD)和UCS-4(4字节存储代码点U+00000000~U+7FFFFFFF)

到unicode2.0时,unicode在编码上已经和UCS基本保持一致。

UTF-16是完全对应于UCS-2规定的代码点的编码形式,即把UCS-2规定的代码点直接使用两个字节的二进制数据保存下来。

UTF-32用四个字节表示代码点,这样就可以完全表示UCS-4的所有代码点, 理论上UCS-4编码范围能达到U+7FFFFFFF,但是因为unicode和iso达成共识,只会用17个平面内的字符,所以UTF-32表示的代码点是UCS-4的子集。

可变长度编码UTF-8仍然是使用最广泛的一种unicode编码形式。


总结一句,unicode和UCS都是字符集,ucs-2和ucs-4用来表示所有unicode字符(或ucs字符)对应的代码点(编号),utf-8、utf-16和utf-32等是计算机中用来对这些代码点(编号)进行存储编码的不同方式。