首页 > Java > 正文

字符编码基础

标签:java, encode

 我们在开发的过程中,常常会遇到乱码的情况。归根结底就是因为编码和解码不一致,计算机无法还原出正确的信息。要搞清楚这个问题,我们首先了解一下相关概念。
字符集合(character set):一组形状的集合,例如所有汉字的集合,与计算机、编码等无关。
编码字符集(coded character set):字符集合中的每一个字符给予一个数字。
字符编码方案(Character-encoding schema):字符编码(数字)映射到一个字节数组的方案。
字符集(charset):一般认为,编码字符集和字符编码方案合起来。
码元(Code Unit):编码方式使用的最小字节组合。
字节序:码元大于一个字节则在存储和传输时就要考虑字节顺序,和芯片类型以及操作系统都有关系。
大端:数据的高字节保存在内存的低地址中。
小端:数据的高字节保存在内存的高地址中。
BOM(byte order mark):添加在数据流开头的字符串,用以描述字节序。

常见的字符集如下。
ASCII码:1字节,0-127。
ISO/IEC 8859字符集:拉丁语系国家,1字节,扩展128-255,ISO/IEC 8859-1到ISO/IEC 8859-15(除12),基本每个规范对应西方国家一个小语种。
GB2312、GBK、GB18030字符集:2字节,兼容ascii,按顺序发展,向前兼容,常用GBK。
其他语言地区:日本JIS,台湾BIG5。

在这样的背景下,通用字符集成为了必然的选择,Unicode应运而生。

Unicode的编码空间被划分为17个平面,每个平面2^16(65536)个码位,BMP平面内,从U+D800到U+DFFF之间(2^11=2048)的码位区块是永久保留不映射到Unicode字符。虽然世界通用的表Unicode是有了,但是有人就发现这有点浪费资源啊。每次让计算机读取三个字节然后参照Unicode表解码,那么像a、b…0、1、2…这些一个字节就够了的就太浪费了。于是uft-8,utf-16,utf-32这些编码方案就出现了。utf-16是用两个字节来编码所有的字符,utf-32则选择用4个字节来编码,utf-8为了节省资源,采用变长编码,编码长度从1个字节到6个字节不等。可由于互联网大部分是1个字节(代码很多英文的),所以最后大家选择用的最多的还是utf-8。

UTF-8最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。
UTF-8的编码规则很简单,只有二条:
1)对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。
2)对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。

Java是用Unicode来表示字符,内部使用UTF-16,一个char是2个字节, U+0000~U+FFFF用一个char,U+10000~U+10FFFF用两个char。如下图所示


原创文章,转载请注明出处!
本文链接:http://wuukee.github.io/posts/encode.html
上篇: TCP连接三次握手四次挥手理解
下篇: 2019无锡马拉松