java中经常会用到编码转换,但是经常会搞混,看了几个大神的解释,加入自己的理解,花了点时间整理下,供查阅。
1、常用编码
目前比较常用的编码有ASCII码,ISO-8859-1,GB2312,GBK,Unicode等
1)ASCII码:仅用计算机的最小存储单位一个字节来标识,即8位,ascii码规定了一个英文字符和二进制位的对应关系,一共规定了128个字符,其中0-31是不能打印的字符,ascii码实际仅占用了后7个二进制位,最高位始终为0;
2)ISO-8859-1
IOS组织在ASCII基础上扩展,低7位仍然是ascii码,利用最高为来表示其余字符,IOS标准有IOS-8859-1 ~ IOS-8859-15,其中1涵盖了大多数西欧字符,应用最广泛,但是还是做多表示256个字符
3)GB2312
GB2312由两个字节组成,涉及到几个概念:
区位码:GB2312将汉字编入94*94的二位表中,行称为区,列称为位,比如一个字在行54,列43 那么它的区位码就是5443
国际码:将区和位上的数字分别加上32(16进制表示就是20H),形成国际码,加上20H的原因是GB2312覆盖了ascii的字母和字符,仅保留了32个不可打印的字符,所以每个区字节和位字节都需要偏移32(就是从33开始).
举个例子:万的区位码是45区82位,转为16进制的区位码是2D52H,加上2020H等于4D72H
机内码:存储中,每个字节无法区分是ascii码还是gb2312,所以微软规定了如果使用gb2312,每个字节的最高为是1,与ascii码区别,最高位设置为1,那么就是将国际码的每个字节加上128(2的7次幂,转为16进制就是每个字节+80H),得到了
机内码=国际码+8080H=区位码+A0A0H
所以万的机内码=2D52H+A0A0H=4D72H+8080H=CDF2H
我们在电脑文本中看到的已经转换的gb2312编码实际上是机内码
4)GBK
是对GB2312的扩展,兼容GB2312,没做过多研究
5)Unicode
unicode 只是符号集,规定了符号的二进制代码,并没有规定如何存储。Unicode有17个平面,每个平面有2^16=65536个Code Point,总共2^16*17=1114112个,所以最后的码位是10FFFF。这个没有详细研究
2. utf-8
unicode的实现方式之一是utf-8,utf-8在实际开发过程中用的最多,所以做了比较详细的记录。
概念:utf-8是一种变长的编码方式,使用1-4个字节标识不同的符号
编码规则:
1)对于单字节的符号,第一位为0,后面7位为unicode码,因此对于英文字母,utf-8编码与ascii码一样
2)对n(n>1)个字节的符号,第一个字节前n位是1,第n+1位为0,后面子节点前来两位一律为10,剩余所有位为unicode码
从编码规则来看,如果第一个字节的第一位是0,那么这个字符就占一个字节,如果第一个字节前几位是1,那么就占几个字节
看下utf-8存储字节和unicode的对应范围
1个字节对应的unicode范围是0000 0000-0000 007F
2个字节对应unicode的范围是0000 0080-0000 07FF
3个字节对应unicode的范围是0000 0800-0000 FFFF
4个字节对应unicode的范围是0001 0000-0010 FFFF
这里unicode都用的4个字节来表示,得详细解释下,先说一个字节
1个字节的二进制范围是0000 0000-0111 1111,转为16进制是00-7F,所以4个字节表示unicode就是0000 0000-0000 007F
2个字节,根据编码规则,第一个字节的前三位必须是110,第二个字节的前两位必须是10,那么第一个字节有5位,第二个字节有6位来存储unicode,即开始范围是1100 0010 1000 0000,开始我比较疑惑为什不从1100 0001 1000 0000开始,随后发现,unicode的0 000100 0000实际上在一个字节的表示范围内。结束范围比较好理解,是11011111 10111111,表示unicode的实际只有0111 1111 1111,即7FF,所以2个字节对应的unicode范围是0000 0080-0000 07FF。
3个字节,2个字节实际表示unicode的位数是11,那么三个字节起始表示unicode的是应该是12位,第一位是1 ,即1000 0000 0000(800H),实际存储的字节则为11100000 10100000 10000000,3个字节实际表示unicode的位数是16位(高4+中6+低6),所以3个字节的范围是FFFFH
4个字节起始unicode应该是17位,最高位为1,则起始为10000H,即11110000 10100000 10000000 10000000,4个字节实际表示unicode的有21位,所以最大为1FFFFF,但是unicode的最后码位是10FFFF,所以4个字节表示unicode的范围是0001 0000-0010 FFFF
看图还是更清楚些
image.png
参考网站:
https://blog.csdn.net/zrf2112/article/details/50718684
http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html
网友评论