字符集
在计算机上的三种字符集
在计算机中每个字符都要使用一个编码来表示,而每个字符究竟使用哪个编码,要取决于使用哪个字符集(charset)。
计算机字符集可归类为三种,单字节字符集(SBCS)、多字节字符街(MBCS)和宽字符集(即Unicode字符集)。
1.单字节字符集(SBCS)
SBCS(Single-Byte Chactacter System)的中文意思是单字符字符系统,它所有的字符都用一个字节的长度,SBCS是一个理论规范。具体实现时有两种字符集:ASCII字符集和拓展ASCII字符集。
ASCII字符集主要用于美国,它使用7位表示一个字符,总共128个字符(0~127),但一个字节有8位,有一位不需要用到,因此人们把最高位永远设为0。后来发展都欧洲,欧洲各个国家的字符就多了,128个不够用,怎么办?人们就用8位表示一个字符,就多出了128位,就是拓展ASCII字符集。
2.多字节字符集(MBCS)
随着计算机普及到更多的国家和地区,字符更加多了,8位单字节系统不够用,为了 表示其他国家的文字,人们多ASCII继续拓展,前面一个字节的表示编码与对应字符不变,多出来的字符用两个字节可以表示的更大的编码对应。
但这样做的坏处是各个国家各玩各的,不统一,可能导致使用一个字符集的程序在另一个字符集的系统上运行是乱码。就诞生了理论的Unicode字符集。
3.Unicode编码
Unicode编码是纯理论的东西,和具体的计算机没有关系(就是它规定了字符和编码的对应,这个是唯一的、一一对应的,和任何计算机没有关系)。
标准化组织ISO提出了Unicode编码方案,它可以容纳世界上所有文字和符号的字符编码方案。这个方案规定任何语言中的任一字符都只对应一个唯一的数字,这个数字被成为代码点(Code Point), 或称为码点、码位,它用十六制书写,并加上U+前缀,比如,‘田’的代码点是U+7530;‘A’的代码点是U+0041。再强调一下,代码点是一个理论的概念, 和具体的计算机无关。
所有字符及其Unicode编码构成的集合就叫Unicode字符集(Unicode Character Set, UCS)。早起用两个字节编码,后来不够用发展到4个字节。
重点来了:
这个只是理论上的字符与码值的对应标准,真正的计算机如何实现(存储)这个编码是有三种方式的。
UTF-8,UTF16, UTF32
UTF-8以字节为单位对Unicode进行编码,(重点:这里的单位是程序在解析二进制流时的最小单元,就是程序每次读取8个bit)。具体储存方式可以在网上搜索,这种储存方式可以用到1~4个字节不定,但优势是没有字节序的烦恼。
UTF-16编码以16位无符号整数为单位,就是字符对应的码点转换位16bit为一个单位的二进制串(重点:程序每次取16位二进制串位一个单位解析)。
这种储存方式很巧妙,空出一个代理区表示码点超出两个字节的部分。
UTF-32编码以32位无符号整数为单位。Unicode码点的UTF-32编码就是该码点值。UTF-32很简单,其编码和Unicode码点一一对应。但一般不采用这种编码方式,主要是4个字节数据占用空间大,会造成存储上的浪费和传输上的低效,因此16位是最好的。
下面说说字节序的问题:
1、单字节没有字节序的问题,一方面是每次读取都是一次取一个字节,另一方面是它在表示上设置了开头的字节与后面的字节不一样。
2、UTF-16(UTF-32类似),一次读取16bit(两个字节),而且两个字节在表示上没有区别,无法看出谁是高位谁是地位。因此就有了高位在起始位置的大端字节序 和 地位在起始位置的小端字节序。
为了识别一个编码的字节序,Unicode标准建议用BOM(Byte Order Mark)来区分字节序, 即在传输字节流前, 先传输被作为BOM的字符,该字符的码点为U+FEFF, 而它的相反FFFE在Unicode中是未定义的码位, 所以两者结合起来可以分别表示字节序, 即BOM字符在大端系统上的编码显示为FEFF; 而在小端系统上的显示为FFFE。通常把BOM字符的编码放在文件开头,如果开头是FEFF,则说明该文件是以大端方式储存的UTF-16编码; 如果文件开头是FFFE, 则说明该文件是以小端方式存储的UTF-16编码。
数据传输过程也一样,如果接受之收到FEFF,就表明这个字节流是大端的;如果接收到FFFE,就表明这个字节流是小端的。
UTF-8不需要BOM来表明字节顺序,但可以用BOM来表明编码方式。BOM的UTF-8编码为EFBBBF。如果文件开头是EFBBBF, 则说明该文件的编码是UTF-8;接收数据类似。
UTF-32有字节顺序区别,它的BOM字符在大端字节序的编码为00 00 FE FF,小端字节序的编码为FF FE 00 00。