字节编码主要是对应二进制数字和字符串直接的转换,人通过字符串可很只管的知道输出要表达的意思。
对初学者而言,字节编码很难选取, 涉及不同编码的转换,更是头疼。本篇选择简单的几个编码方式进行加深记忆。
选取几种常用的编码方式:
UTF-8,GBK,UNICODE,ASCII
分别对字母,汉字进行编码
通过几种编码方式对String进行编码后的内容、长度进行比较,看哪种最适合平时使用
测试代码:
package com.study.code; import java.io.UnsupportedEncodingException; import java.util.Arrays; public class CodeTest { //比较几种编码对 字母 和汉字 转换后占用存储的大小 public static void main(String[] args) throws UnsupportedEncodingException { System.out.println( "================ 字母test ===============" ); String a = "test"; System.out.println( "默认 : " + a.getBytes().length +" " + showByte(a.getBytes() )); System.out.println( "utf-8 : " + a.getBytes("UTF-8").length +" " + showByte(a.getBytes("UTF-8") )); System.out.println( "GBK : " + a.getBytes("GBK").length +" " + showByte(a.getBytes("GBK") )); System.out.println( "UNICODE : " + a.getBytes("UNICODE").length +" " + showByte(a.getBytes("UNICODE") )); System.out.println( "ASCII : " + a.getBytes("ASCII").length +" " +showByte(a.getBytes("ASCII") ) ); System.out.println( "================ 汉字测试 ===============" ); a = "测试"; System.out.println( "默认 : " + a.getBytes().length +" " + showByte(a.getBytes() )); System.out.println( "utf-8 : " + a.getBytes("UTF-8").length +" " + showByte(a.getBytes("UTF-8") )); System.out.println( "GBK : " + a.getBytes("GBK").length +" " + showByte(a.getBytes("GBK") )); System.out.println( "UNICODE : " + a.getBytes("UNICODE").length +" " + showByte(a.getBytes("UNICODE") )); System.out.println( "ASCII : " + a.getBytes("ASCII").length +" " +showByte(a.getBytes("ASCII") ) ); }
//将二进制数组转换为字符串展示 public static String showByte(byte[] b){ String ret = ""; for(byte a : b){ ret += Integer.toBinaryString(a) .toString() ; //a 转为int 后再重新转为二进制数据 会生成32位 ,所以结果是32* 字节长度 } return ret; } }
结果输出为:
================ 字母test =============== 默认 : 4 1110100110010111100111110100 utf-8 : 4 1110100110010111100111110100 GBK : 4 1110100110010111100111110100 UNICODE : 10 111111111111111111111111111111101111111111111111111111111111111101110100011001010111001101110100 ASCII : 4 1110100110010111100111110100 ================ 汉字测试 =============== 默认 : 6 111111111111111111111111111001101111111111111111111111111011010111111111111111111111111110001011111111111111111111111111111010001111111111111111111111111010111111111111111111111111111110010101 utf-8 : 6 111111111111111111111111111001101111111111111111111111111011010111111111111111111111111110001011111111111111111111111111111010001111111111111111111111111010111111111111111111111111111110010101 GBK : 4 11111111111111111111111110110010111111111111111111111111111000101111111111111111111111111100101011111111111111111111111111010100 UNICODE : 6 1111111111111111111111111111111011111111111111111111111111111111110110110010111111111111111111111111111000101111111111111111111111111111010101 ASCII : 2 111111111111
结论:
ASCII 是最简单的西文编码方案,识别不了汉字,只能识别128 或256 种可能的字节。其余字符串会按照字符串长度填充1 ; 在英语中,用128个符号编码便可以表示所有,但是用来表示其他语言,128个符号是不够的.
utf-8
如果一个符号只占一个字节,那么这个8位字节的第一位就为0。
如果为两个字节,那么规定第一个字节的前两位都为1,然后第一个字节的第三位为0,第二个字节的前两位为10。如果是三个字节的话,那么第一个字节的前三位为111,第四位为0,剩余的两个字节的前两位都为10。
按照这样的算法去思考一个中文字符的UTF-8是怎么表示的:一个中文字符需要两个字节来表示,两个字节一共是16位,那么UTF-8下,两个字节是不够的,因为两个字节下,第一个字节已经占据了三位:110,然后剩余的一个字节占据了两位:10,现在就只剩下11位,与Unicode下的两个字节,16位去表示任意一个字符是相悖的。所以就使用三个字节去表示非ANSI字符:三个字节下,一共是24位,第一个字节头四位是:1110,后两个字节的前两位都是:10,那么24位-8位=16位,刚好两个字节去表示Unicode下的任意一个非ANSI字符。这也就是为什么UTF-8需要使用三个字节去表示一个非ANSI字符的原因了!
Unicode符号范围 | UTF-8编码方式
(十六进制) | (二进制)
--------------------+---------------------------------------------
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
utf-8中文3个字节,英文1个字节
GBK
全称《汉字内码扩展规范》 向下与 GB 2312 编码兼容,向上支持 ISO 10646.1国际标准
gbk中文2个字节,英文1个字节;