一.常见的几种编码格式
1.ASIIC
最早的计算机使用的编码方式,使用一个字节表示一个字符;
特点
用0-127(7位)表示一个字符
2.GB2312
计算机流入中国后,因为ASIIC只使用一个字节表示字符,而汉字有好几千个,1个字节无法满足表示所有汉字的需求。
特点
①用双字节表示一个汉字,单字节表示一个英文字符(保持和ASIIC一致)
②一个小于127的字符的意义和原来相同,但是两个大于127的字符连在一起时表示一个汉字;
③范围:低字节(A1-F7),高字节(A1-FE)
④解码时,逐个字节检查,如果该字节的值小于127,则表示这个字符是一个ASIIC字符。如果这个字节的值大于127,则这个字节是中文字符的一部分,接着检查其后面一个字符。将前后两个字符组合起来,就可以得到该中文字符的GB2312编码,接着转换为中文字符;
3.GBK
GBK的出现是因为GB2312可以表示字符还是不够用,很多中文字符在GB2312标准中还是无法表示,因此,对GB2312标准做了一些修改,衍生出GBK。
特点:
①和GB2312一样,GBK也使用2个字节表示中文字符,使用一个字节表示ASIIC码;
②中文字符的第一个字节大于127,第二个字节没有小于127的限制。解码时通过确定某一个字节是否大于127来确定是某一个中文字符的开始;
③范围:低字节(0-255),高字节(A1-FE)
④解码时,逐个字节检查,如果出现某个字节的大于127,则该字节表示某个中文字符的高位,其后面一个字符不管是否大于127一定是该中文字符的低位.
4.Unicode
国际统一标准。
为了解决不同国家针对不同类型的编码方式,ISO制定了一种可以统一所有标准的编码标准(划重点,是统一,非兼容);
特点:
①unicode标准使用两个字节表示任何字符(中文,英文,ASIIC,Korea,欧洲字符等)。ASIIC字符用unicode编码时,其第一个字节为0;
②范围:高字节(0-255),低字节(0-255)
③解码时,从文件开头,每两个字节组合成一个字符的编码,对其解码并结合unicode表,即可解码;
5.UTF8
unicode统一了不同语言的编码格式,但是unicode字符在存储时存在一个问题,会造成存储空间的浪费。试想,一个全部是英文字符的文件通过unicode编码格式存储时,其存储空间存在一半的空间是无效的。因为英文字符用一个字节就可以区分。utf8为了解决这个问题出现;
特点:
①基本规则:
- 对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。
- 对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。
②编码
根据字符在unicode表中的位置决定改字符使用哪种模式存储。utf8提供了三种模式:
模式 | UTF8 | UNICODE |
---|---|---|
单字节 | 0xxxxxxx | 0000 – 007F |
双字节 | 110xxxxx 10xxxxxx | 0080 – 07FF |
三字节 | 1110xxxx 10xxxxxx 10xxxxxx | 0800 – FFFF |
解释:
单字节模式:对于unicode编码在0000-007F范围内的字符,其utf8编码为单字节,该字节最高位固定为0,其他位是unicode码的二进制格式;
如:
字符’a’在unicode编码表中是0x61,其二进制位110 0001,因此,其UTF8编码为:0110 0001
双字节模式:对于unicode编码在0080-07ff范围内的字符,其utf8编码为双字节,取其二进制码的低6位存入低字节的xxxxxx,剩下的位存入高字节的xxxxx,位数不够,高位补0;
如:
‘Σ’字符在unicode编码中位03A3,二进制格式为:11 1010 0011,
根据03A3,可以确定其应使用双字节存储,因此,其模板为110xxxxx 10xxxxxx,将0011 1010 0011的后6位100011填入10xxxxxx,剩下的位1110填入110xxxxx,则得到’Σ’的utf8编码为:11001110 10100011;
三字节模式:对于unicode编码在0800-FFFF范围的字符使用三字节编码,具体的转换过程参考单、双字节模式即可;
③解码
从编码的过程可以看出,utf8编码格式针对不同的unicode格式有3中模式,通过其模式的特点就可以划分出两个字符之间的界限,从而完成解码;
以三字节解码为例:
原字符:hello,世界
对这些字符进行UTF8编码,查看其二进制格式:
Hex: 6865 6c6c 6f2c e4b8 96e7 958c
Bin:
01101000 01100101 01101100 01101100 01101111 00101100
11100100 10111000 10010110 11100111 10010101 10001100
接下来,我们就需要用这些二进制串来匹配其unicode码;
以01101000为例,其第一位是0,三种模式中只有单字节模式的首位为0,因此,01101000表示一个单字节,去掉首位后,得到其unicode编码为1101000=104,104在unicode对照表中对应的就是字符h;h后面的5个字节都是这种单字节模式,过程不再赘述;
11100100 10111000 10010110这一串二进制码,首字节以1110开头,因此,根据UTF8的基本规则2,我们可以知道这三个字节是三字节模式。按照规则可以得到其unicode码:01001110 00010110,即19990,通过查找unicode对照表即可知道其对应的字符是’世’,后面一个字符的解码过程不再赘述;
二.GBK和UTF8的相互转换
前面介绍了UTF8和UNICODE两种编码的编解码规则,UTF8是为解决unicode存储问题而出现的。有个问题,GBK和unicode是否有直接的转换规则。答案是没有。因为GBK是针对中文出的编码方式,而Unicode是ISO为了统一世界上所有的编码方式而出现的。因此,unicode制定时并没有兼容GBK,同一个字符在GBK和unicode上面的编码只能通过一一映射对应起来。因此,GBK无法和UTF8直接完成转换,UTF8要转换为GBK,需要先转换为UNICODE,之后再转换为GBK。
附录
参考链接:
彻底搞懂编码ASCII、Unicode、GBK 和 UTF8 、UTF-16、UTF-32编码方式
该博主讲的很细,非常值得一看~~