转自:http://cenalulu.github.io/linux/character-encoding/
简单地说字符集就规定了某个文字对应的二进制数字存放方式(编码)和某串二进制数值代表哪个文字(解码)的转换关系。
文字<---------->二进制数据字符串
编码集对应
字符集 | 16进制编码 | 对应的二进制数据 |
UTF-8 | 0xE5B18C | 111001011011000110001100 |
UTF-16 | 0x5C4C | 101110001001100 |
GBK | 0x8CC5 | 1000110011000101 |
对于一个字符集来说要正确编码转码一个字符需要三个关键元素:字库表(character repertoire)、编码字符集(coded character set)、字符编码(character encoding form)。
code point
来表示一个字符在字库中的位置。code point
的值作为编码后的值直接存储。例如在ASCII中A
在表中排第65位,而编码后A
的数值是0100 0001
也即十进制的65的二进制转换结果。
统一字库表的目的是为了能够涵盖世界上所有的字符,但实际使用过程中会发现真正用的上的字符相对整个字库表来说比例非常低。例如中文地区的程序几乎不会需要日语字符,而一些英语国家甚至简单的ASCII字库表就能满足基本需求。而如果把每个字符都用字库表中的序号来存储的话,每个字符就需要3个字节(这里以Unicode字库为例),这样对于原本用仅占一个字符的ASCII编码的英语地区国家显然是一个额外成本(存储体积是原来的三倍)。于是就出现了UTF-8这样的变长编码。在UTF-8编码中原本只需要一个字节的ASCII字符,仍然只占一个字节。而像中文及日语这样的复杂字符就需要2个到3个字节来存储。
Unicode就是上文中提到的编码字符集,而UTF-8就是字符编码,即Unicode规则字库的一种实现形式。
为了更好的理解后面的实际应用,我们这里简单的介绍下UTF-8的编码实现方法。即UTF-8的物理存储和Unicode序号的转换关系。
UTF-8编码为变长编码。最小编码单位(code unit
)为一个字节。一个字节的前1-3个bit为描述性部分,后面为实际序号部分。
具体每个字节的特征可见下表,其中x
代表序号部分,把各个字节中的所有x
部分拼接在一起就组成了在Unicode字库中的序号
简单的说乱码的出现是因为:编码和解码时用了不同或者不兼容的字符集
原文:http://www.cnblogs.com/zhuqn/p/4252109.html