字符编码
起源
计算机不能直接识别字符(文本的最小组成单位)。
抽象字符和数字成对编码用于在计算机系统中表示的信息单位。虽然字符本身是抽象的,但它一旦存在与计算机系统中,它就对应了某种特定字符编码方式。计算机可以识别二进制数,于是采用一个二进制数来指代一个字符。
编码与解码
- 编码过程:字符转换成二进制刘表示的过程
- 解码过程: 二进制刘转换成字符的过程
- 编码规则:编码和解码过程中遵循的规则,例如GBK编码,UTF-8编码
区分几个基本概念:
字符是各种文字和符号的总称,包括各个国家文字、标点符号、图形符号、数字等。字符集是多个字符的集合,字符集种类较多,每个字符集包含的字符个数不同,常见字符集有:ASCII字符集、ISO 8859字符集、GB2312字符集、BIG5字符集、GB18030字符集、Unicode字符集等。计算机要准确的处理各种字符集文字,需要进行字符编码,以便计算机能够识别和存储各种文字。
编码(encoding)和字符集不同。字符集只是字符的集合,不一定适合作网络传送、处理,有时须经编码(encode)后才能应用。如Unicode可依不同需要以UTF-8、UTF-16、UTF-32等方式编码。字符编码就是以二进制的数字来对应字符集的字符。使用哪些字符。也就是说哪些汉字,字母和符号会被收入标准中。所包含“字符”的集合就叫做“字符集”。规定每个“字符”分别用一个字节还是多个字节存储,用哪些字节来存储,这个规定就叫做“编码”。
各个国家和地区在制定编码标准的时候,“字符的集合”和“编码”一般都是同时制定的。因此,平常我们所说的“字符集”,比如:GB2312, GBK, JIS 等,除了有“字符的集合”这层含义外,同时也包含了“编码”的含义。
注意:Unicode字符集有多种编码方式,如UTF-8、UTF-16等;ASCII只有一种;大多数MBCS(包括GB2312)也只有一种。
字符编码的历史
ASCII
美国信息交换标准代码,最早的通用编码方案。开始时,只用7个比特位就表示完了所用拉丁文子没有和一些符号,共128个。后来发现不够用,又启用了第8位,刚好一个字节的长度,共256个字符。
但是,不同的公司/组织吧这拓展出来的128个码位指派给了不同的字符,文档交流就困难了。于是ANSI这个组织站出来了,制定了ANSI标准。
而且人们也发现,ASCII这种单字节(因为它占8个比特位)编码满足不了更多的字符需求,那必须得用多个字节编码。多字节字符集(MBCS)概念就诞生了。
ANSI
美国国家标准协会认可的标准。注意,它是一种标准,而不是某种具体编码,可以看做是编码的一种分类。ANSI的标准就是,ASCII码占用的码位及其所指代的字符不许改变,剩下的自己扩展。
中国人在这个规定上有自己的扩展(如GBK),英国人也有自己的扩展(如ISO-8859-1,即latin-1)。所以ISO-8859-1和GBK都可以称之为ANSI编码,因为它们符合ANSI规定。以Windows系统为例,中文系统中所指的ANSI编码就是GBK,英文系统中的ANSI编码就是ISO-8859-1。
MBCS
多字节字符集(Multi-Byte Character Set),采用不定长度可以是一个字节,也可以是两个字节,也可以是三个字节来进行编码。大多数情况下2个字节就够用了,汉字就分配两个字节,称之为DBCS(Double-Byte Chactacter Set)。
在Linux系统中看得到MBCS说法,在Windows中呢?其实就是ANSI,ANSI只规定了第一个字节的位置是ASCII,超出这个范围的,肯定也是多字节的了。
Unicode字符集
通过以上的介绍知道,各种解决方案都是各自为政,解决不了 “同一个系统中同时显示全宇宙的所有字符” 这个问题。
于是就有两个组织,他们开始着手做这件事情,UCS和Unicode诞生了。
通用字符集(UCS,Universal Character Set)是由国际标准化组织(ISO)制定的 ISO 10646标准所定义的字符集。通常也译为通用多八位编码字符集。统一码(Unicode)是由统一码联盟指定的。
后来发现,一山不容二虎,世界人民不需要两个目的相同但是具体实现却有差异的编码方案。UCS和Unicode握手言和,从 Unicode 2.0 起,采用了和ISO 10646-1的编码方案,它们在相同的码位上都对应同样的字符。尽管这两个组织目前还在相互独立的在发布字符编码标准。
可能是Unicode名字好记,所以采用更为广泛。关于UCS-2,UCS-4这些概念不再赘述。
Unicode,UTF-8,UTF-16它们是什么关系
UTF-8(Unicode Transformation Format)即Unicode转换格式,8的意思是使用8比特为单位来进行编码。码位小于128时,就是对应的字节值;大于等于128时,就会转换成2、3、4字节的序列。每个字节的序列值介于128~255。
GBK,GB2312,Latin-1,Big-5,ASCII等,它们的字符集和具体编码实现方式绑定(如GBK字符集就采用GBK编码方式),即字符和存储在介质上的二进制流一一对应。缺陷很明显,字符集扩展性差。Unicode考虑了这个问题,所以它的编码与编码的实现方式没有绑定。而是有多种实现方式,如UTF-8,UTF-16,UTF-32。
例如字符‘A’在Unicode中的编码是65,但存储在介质上时,二进制流的十六进制表示采用UTF-8时是0x41,而UTF-16大端模式是0x00 0x41。
Reference:
深度剖析java编码
字符编码详解——彻底理解掌握编码知识,“乱码”不复存在