常见字符集和编码方式
ASCII
、Unicode
、GBK
、GBK2312
、UTF-8
这些字符集和编码方式的名词总是让我们纠结,那么他们有什么区别呢?
一般来讲,除了UTF-8
是字符集Unicode
的编码方式,其余的例如ASCII
、GBK
等都属于字符集,它们为每一个字符集的字符都赋予了一个值,这个值可以是一个字节大小
,也可能是两个字节、三个字节等;
- 基础的
ASCII
字符集是单字节字符集,用一个7位二进制数表示128个字符; Unicode
旨在包含表示世界上所有语言的的字符,目前主要有UCS-2
和UCS-4
,分别采用两个字节和四个字节来表示每一个字符;GBK2312
是采用两个大于127
字节来表示汉字,一个小于或等于127
的字节维持ASCII的语义的一种字符集;GBK
是GBK2312
的一种扩展,要求高低两字节中的,低字节不需要是大于127
的字节,因此表示的字符数得到扩展;UTF8
是Unicode
字符集的一种编码方式,以便于适合在网络上传输和电脑存储;
Unicode
字符集和UTF8
编码有很强的联系;具体联系是这样的:
- 单字节的字符,字节的第一位设为0,对于英语文本,UTF-8码只占用一个字节,和ASCII码完全相同;
- n个字节的字符(n>1),第一个字节的前n位设为1,第n+1位设为0,后面字节的前两位都设为10,
这n个字节的其余空位填充该字符unicode码,高位用0补足
这样就形成了如下的UTF-8标记位:
Unicode(16进制) | UTF8(2进制) |
---|---|
0x0000 - 0x007F | 0xxxxxxx |
0x0080 - 0x07FF | 110xxxxx 10xxxxxx |
0x0800 - 0xFFFF | 1110xxxx 10xxxxxx 10xxxxxx |
0x010000 - 0x10FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
…… | …… |
Unicode
中大部分汉字是采用2字节表示的,因此UTF8
编码后大小是3字节;
但是有些少数不常见的汉字是采用3字节表示的,因此UTF8
编码后大小是4字节;
例子:
public static String byteArray2BinaryString(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(Integer.toBinaryString(Byte.toUnsignedInt(b)));
sb.append(" ");
}
return sb.toString();
}
汉字:��
System.out.println("Unicode: " + Long.toBinaryString((long)"��".codePointAt(0)));
System.out.println("UTF8: " + byteArray2BinaryString("��".getBytes("utf8")));
输出如下:
Unicode: 100000000010111111
UTF8: 11110000 10100000 10000010 10111111
��的Unicode
值是100000**000010**111111一共18位,因此是3字节字符;对应的UTF8
编码是4字节,因此格式为:11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
;
将unicode
补全成对应的UTF8
编码后是:
11110**000** 10**100000** 10**000010** 10**111111**
对于常见的汉字,一般来讲GBK编码比UTF8编码少一个字节(utf8= 1.5 * gbk),因此有时候采用GBK编码来节省带宽和存储空间;对于英文字符,两者编码都是采用单字节来编码,因此无异;
例子:
对于汉字 中
分别进行UTF8
和GBK
编码
System.out.println("UTF8: " + byteArray2BinaryString("中".getBytes("utf8")));
System.out.println("GBK: " + byteArray2BinaryString("中".getBytes("gbk")));
输出如下:
UTF8: 11100100 10111000 10101101
GBK: 11010110 11010000
总结:
- UTF8
是Unicode
字符集的一种编码方式,主要用与信息传输和存储;
- GBK
编码对于汉字要比UTF8
节省空间,但是不是全球通用,有些环境下会出现乱码;
- UTF-8
中大部分汉字采用3字节表示,少些复杂的字采用4字节表示;分别对应的Unicode
也是2字节和3字节;