常见字符编码
字符集:字符比如各国文字符号,字母,特殊符号等等的集合。编码:规定每个字符分别用一个字节,还是多个字节,字节顺序等来表示一个字符。
1. ASCII码
美国在60年代制定的一套字符编码,用单字节(8位)表示一个字符,后使用7 位二进制数来表示所有的大写和小写字母,数字0 到9、标点符号, 以及在美式英语中使用的特殊控制字符,总共能表示128个字符。
各国有各种各样的语言字符,ASCII显然不能表达完全。这样各国久催生出自己的编码标准,也即第2节介绍的ANSI编码。
2. ANSI编码
不同的国家和地区制定了不同的标准,由此产生了 GB2312、GBK、Big5、Shift_JIS 等各自的编码标准。这些使用 1 至 4 个字节来代表一个字符的各种汉字延伸编码方式,称为 ANSI 编码(编码统称)。
2.1 中文常涉及的编码标准
2.1.1 GB2312
作用:国家简体中文字符集(中国大陆),兼容ASCII。位数:使用双字节表示,能表示7445个符号,包括6763个汉字,几乎覆盖所有高频率汉字。 范围:高字节从A1到F7, 低字节从A1到FE。将高字节和低字节分别加上0XA0即可得到编码。
2.1.2 Big 5
作用:统一繁体字编码(中国香港、中国台湾)。位数:使用双字节表示,表示13053个汉字。范围:高字节从A1到F9,低字节从40到7E,A1到FE。
2.1.3 GBK
作用:它是GB2312的扩展,加入对繁体字的支持,兼容GB2312。位数:使用双字节表示,可表示21886个字符。范围:高字节从81到FE,低字节从40到FE。
2.1.4 GB18030
作用:它解决了中文、日文、朝鲜语等的编码,兼容GBK。位数:它采用变字节表示(1 ASCII,2,4字节),可表示27484个文字。范围:1字节从00到7F; 2字节高字节从81到FE,低字节从40到7E和80到FE;4字节第一三字节从81到FE,第二四字节从30到39。
2.2常见的外文编码
2.2.1 ISO-8859-1(Latin-1)
作用:扩展ASCII,表示西欧、希腊语等。位数:单字节编码,ASCII为基础,在空置的0xA0-0xFF的范围内,加入96个字母及符号,藉以供使用变音符号的拉丁字母语言使用。范围: 0x00-0xFF,0x00-0x7F之间完全和ASCII一致,0x80-0x9F之间是控制字符,0xA0-0xFF之间是文字符号。
1.2.2 Shift_JIS
作用:一个日本电脑系统常用的编码表。它能容纳全角及半角拉丁字母、平假名、片假名、符号及日语汉字。位数:双字节表示。
3. 常见的统一编码
Unicode字符集
各个国家采用各自的编码,国际间信息交流更加方便,这就催生了全球字符统一编码格式的诞生。标委会将世界上所有的符号都纳入其中,每一个符号都给予一个独一无二的编码, 这就是Unicode(unique code),就像它的名字都表示的,这是一种所有符号的编码,那么乱码问题就会消失。Unicode用数字0-0x10FFFF来映射这些字符,最多可以容纳1114112个字符,或者说有1114112个代码点(任何文字在Unicode中都对应一个值,这个值称为代码点)。
3.1 UCS(UniversalCharacter Set),通用字符集
国际标准 ISO10646 定义了通用字符集, UCS 是所有其他字符集标准的一个超集。它保证与其他字符集是双向兼容的,就是说,如果任何文本字符串翻译到 UCS格式,然后再翻译回原编码,不会丢失任何信息。
3.1.1 UCS-2
UCS-2是用两个字节来表示代码点,其取值范围为U+0000~U+FFFF。
3.1.2 UCS-4
为了能表示更多的文字,人们又提出了UCS-4,即用四个字节表示代码点。它的范围为 U+00000000~U+7FFFFFFF,其中 U+00000000~U+0000FFFF和UCS-2是一样的。
3.2 UTF编码
Unicode只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。比如,汉字“严”的Unicode是十六进制数4E25,转换成二进制数足足有15位(100111000100101),也就是说这个符号的表示至少需要2个字节。表示其他更大的符号,可能需要3个字节或者4个字节,甚至更多。这里就有两个严重的问题:
如何才能区别Unicode和ASCII?计算机怎么知道三个字节表示一个符号,而不是分别表示三个符号呢?
第二个问题,英文字母只用一个字节表示就够了。如果Unicode统一规定,每个符号用三个或四个字节表示,那么每个英文字母前都必然有二到三个字节是0,这对于存储来说是极大的浪费,文本文件的大小会因此大出二三倍,这是无法接受的。
它们造成的结果是:1)出现了Unicode的多种存储方式,也就是说有许多种不同的二进制格式,可以用来表示Unicode。2)Unicode在很长一段时间内无法推广,直到互联网的出现。为了规定存储,标委会推出常见的UTF(Unicode TransformationFormat)。
3.2.1 UTF-8
互联网的普及,强烈要求出现一种统一的编码方式。UTF-8就是在互联网上使用最广的一种Unicode的实现方式。位数:1~4个字节表示一个字符,根据不同的符号而变化字节长度。UTF-8的编码规则很简单,只有二条:
l 对于单字节的符号,字节的第一位设为0,后面7位为这个符号的Unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。
l 对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的Unicode码。
3.2.2 UTF-16
位数:双字节表示字符。范围:对于小于0x10000的UCS码,UTF-16编码就等于UCS码对应的16位无符号整数。对于不小于0x10000的UCS码,定义了一个算法。不过由于实际使用的UCS-2,或者UCS-4的BMP必然小于0x10000,所以就目前而言,可以认为UTF-16和UCS-2基本相同。但UCS-2只是一个编码方案,UTF-16却要用于实际的传输,所以就不得不考虑字节序的问题。
3.2.3 UTF的字节序和BOM
UTF-8以字节为编码单元,没有字节序的问题。UTF-16以两个字节为编码单元,在解释一个UTF-16文本前,首先要弄清楚每个编码单元的字节序。例如“奎”的Unicode编码是594E,“乙”的Unicode编码是4E59。如果我们收到UTF-16字节流“594E”,那么这是“奎”还是“乙”?
Unicode规范中推荐的标记字节顺序的方法是BOM。在UCS编码中有一个叫做"ZEROWIDTH NO-BREAKSPACE"的字符,它的编码是FE FF。而FF FE在UCS中是不存在的字符,所以不应该出现在实际传输中。UCS规范建议我们在传输字节流前,先传输字符"ZEROWIDTH NO-BREAK SPACE"。这样如果接收者收到FE FF,就表明这个字节流是Big-Endian的;如果收到FF FE,就表明这个字节流是Little-Endian的。因此字符"ZEROWIDTH NO-BREAK SPACE"又被称作BOM。
UTF-8不需要BOM来表明字节顺序,但可以用BOM来表明编码方式。字符“ZERO WIDTH NO-BREAKSPACE”的UTF-8编码是EF BB BF。所以如果接收者收到以EF BB BF开头的字节流,就知道这是UTF-8编码了。
3.3 UCS Big Endian和 UCS Litte Endian
Unicode码可以采用UCS-2格式直接存储。同样前面加入“零宽度非换行空格”(FE FF),
如果一个文本文件的头两个字节是FE FF,就表示该文件采用UCS BigEndian;如果头两个字节是FF FE,就表示该文件采用UCS Litte Endian。
4. 总结
计算机字符编码到目前位置大致分为三个阶段:
阶段 | 编码统称 | 说明 |
一 | ASCII | 计算机刚开始只支持英语,其它语言不能够在计算机上存储和显示。 |
二 | ANSI | 不同的国家和地区制定了不同的标准,由此产生了 GB2312, BIG5, Shift_JIS 等各自的编码标准。这些使用 1或多个字节来代表一个字符的各种文字延伸编码方式,称为 ANSI 编码。 |
三 | UNICODE 编码系列 | 为了使国际间信息交流更加方便,国际组织制定了 UNICODE 字符集,为各种语言中的每一个字符设定了统一并且唯一的数字编号,以满足跨语言、跨平台进行文本转换、处理的要求。同时对Unicode字符集采用不同标准的编码,如UTF-8,UTF-16,UCS-2 Litte Endian等。 |