发现网上关于编码的文章挺多,但是说的彻底清楚的基本没有,所以还是得自己来总结,毕竟每个人的基础不一样,所以只有每个人自己总结的才能透彻的理解。
关于unicode:
大家都知道unicode又叫统一码、万国码。可以百科一下unicode的定义:
Unicode是一种在计算机上使用的字符编码。它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。
... 只用2个字节就可以编码地球上几乎所有地区的文字。因此,创建了UNICODE编码。
注意上说的是2个字节可以编码“几乎”所有地区的文字,所以并不是世界上所有的字符都能用2个字节来编码,因此就有了UCS-2与UCS-4.
下面解释一下UCS-2与UCS-4:
UCS:通用字符集(Universal Character Set)是由ISO制定的ISO 10646(或称ISO/IEC 10646)标准所定义的标准字符集。
Unicode 是基于UCS的标准来发展,并且同时也以书本的形式对外发表.
UCS-2用两个字节编码unicode,UCS-4用4个字节编码unicode。
弄清Unicode 与UTF的关系:
1,Unicode是世界上所有字符的一个集合,世界上的每个字符都有一个唯一的unicode编码数值,Unicode用数字0-0x10FFFF来映射这些字符,最多可以容纳1114112个字符.
2,UTF是表示对Unicode的编码方式,通俗的说就是对Unicode的存储方式。
一般常用的有这么几种编码:
UTF-8, UTF-16, UTF-32
3,Unicode是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案。Unicode用数字0-0x10FFFF来映射这些字符,最多可以容纳1114112个字符,或者说有1114112个码位。码位就是可以分配给字符的数字。UTF-8、UTF-16、UTF-32都是将数字转换到程序数据的编码方案。
下面看看UTF-8:
UTF-8以字节为单位对Unicode进行编码。从Unicode到UTF-8的编码方式如下:
Unicode编码(16进制)
|
UTF-8 字节流(二进制)
|
000000 - 00007F
|
0xxxxxxx
|
000080 - 0007FF
|
110xxxxx 10xxxxxx
|
000800 - 00FFFF
|
1110xxxx 10xxxxxx 10xxxxxx
|
010000 - 10FFFF
|
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
总结:世界上所有的字符都能够用unicode来表示,Unicode用数字0-0x10FFFF来映射这些字符,最多可以容纳1114112个字符。
那么如果一个字符的编码是unicode的最大值0x10FFFF(21位),那么最少需要3个字节来表示这个字符。
长久以来,Unicode在我心中的概念就是:使用2个字节来编码字符,可以表示世界上所有的字符。但这种理解是错误的!
网上很多对unicode的定义里面说的:“ 只用2个字节就可以编码地球上几乎所有地区的文字”,是很蛋疼的一句话。虽然没错,但是很容易让新手产生误解,以为2个字节就可以表示所有的unicode编码了。很明显,至少要3个字节才能表示完unicode(世界上所有字符)。
UTF-8、UTF-16、UTF-32都是将数字转换到程序数据的编码方案。都是对unicode的编码方案。
Unicode最初被设计出来的时候希望使用2个字节就可以表示世界上的所有字符。因此,实现Unicode最直接的想法就是用两个字节来存储一个字符,如果大家都这么想就好了,这样一个字符就可以用2个字节长的短整形来存储,但是
1个字符=2个字节在现实中却遇到了麻烦。一方面,用2个字节表示一个字符,浪费了大量的空间(如果仅仅用来存储ISO-Latin字符集里的字符的话);另一方面,人们在实践中发现即使用2个字节编码也无法表示所有字符,因此出现了UTF-16。UTF-16除了使用2个字节编码外,还使用一对2个字节来表示Unicode里很少用到的字符;另外还有UTF-32,它使用单独的4个字节来编码所有的Unicode字符。
UTF-8的好处:使用不定长字节编码unicode,存储ASCII字符只需一个字节,节省空间流量。(欧美国家肯定喜欢,因为他们很少用到中文之类的字符)
UTF-16的好处:UTF-16比起UTF-8,好处在于大部分字符都以固定长度的字节 (2字节) 储存使用2个字节编码unicode,处理数据速度更快。
比如“中国abc你好”这个字串,如果用不定长的UTF-8编码来存储,那么取‘好’这个字符的时候,要计算“中国abc你”占几个字节,然后再把指针移到‘好’,但是如果用UTF-16来存储,直接就可以算出“好”的位置,因为一个字符占2个字节。如果用UTF-8当数据量很大的时候,定位就更加麻烦.
UTF-32:对每一个Unicode码位使用4个字节。其它的Unicode transformation formats则使用不定长度编码(UTF-16在表示超过2byte的字集时,编码长度不是2个字节)。虽然每一个码位使用固定长定的字节看似方便,它并不如其它Unicode编码使用得广泛。主要是太浪费空间了。
补充:问题:为什么有了Unicode还要有UTF-8?
需要注意的是,Unicode 只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。 它们造成的直接结果是:出现了unicode 的多种存储方式,也就是说有许多种不同的二进制格式,可以用来表示 unicode 。 网络上流行的utf-8就是unicode编码的一类应用.
就如同ASCII一样,ASCII字符都是使用一个字节存储的。因为一个字节就能表示完所有的ASCII字符了。你也可以发明一种新的编码方式,蛋疼的使用2个字节来存储ASCII字符。但肯定不会有人使用你的这种编码。
UTF-8编码就是发明的一种比较好的编码unicode字符的方式,基本上网络上都是使用UTF-8的编码来存储unicode字符。这样比较省空间,传输的时候省流量。但是使用的时候很多时候会转换成UTF-16了来使用,这样好处理数据,不清楚的可以看上面UTF-16的好处。
2,字符编码的作用:
字符是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等。字符集是多个字符的集合,字符集种类较多,每个字符集包含的字符个数不同,常见字符集名称:ASCII字符集、GB2312字符集、BIG5字符集、 GB 18030字符集、Unicode字符集等。
计算机要准确的处理各种字符集文字,需要进行字符编码,以便计算机能够识别和存储各种文字。
如果不编码的话,比如一个数字65,计算机怎么知道它代表个什么?因此我们必须使用字符编码,比如ASCII码,告诉计算机65代表的就是字符‘A’。计算机只能与数字打交道,如果你让它存一个字符‘B’,如果不使用字符编码,它也不知道怎么做。使用字符编码之后,计算机就会存储66来表示‘B’
3,关于乱码:
世界上存在着多种编码方式,同一个二进制数字可以被解释成不同的符号。因此,要想打开一个文本文件,就必须知道它的编码方式,否则用错误的编码方式解读,就会出现乱码。
Unicode存储时有个字节序问题,就是一个多字节数字,是从大到小排列还是反之。这和CPU处理有关,一般x86处理时都是倒置的,即大数在前。就像“莫”字的Unicode码0x83ab,按Big Endian就变成了0xab83。
因为Unicode存储时字节序的问题,在Unicode文本前插入一个不存在的字符(ZERO WIDTH NO-BREAK SPACE)作为标志来分辨两种字节序。
UTF-8以单字节为基本单位,所以不存在字节序的问题。