从byte(字节)的bit(位)层面去理解编码(玩爆底层篇)
话不多说,直接上干货
干货结论:
- java不论是负数还是正数在定义、存储、计算的过程中,都是用其补码
- 第二个结论需要自己去体会,详情看下面的2.从byte(字节)的bit(位)层面去理解编码
论证说明:
1.Byte类型用二进制八进制十六进制定义数值类型数据举例
用byte存一个负数,比如负27,我们一般情况下用十进制可以这样表示:
byte b1 = -27;
- 1
那么用二进制如何去声明负27这个数呢?用气原码,反码,还是补码去声明呢?
我们都知道负27这个数,其:
原码:1001 1011
反码:1110 0100
补码:1110 0101
这里我先直接告诉大家,定义-27这个数的时候用的是补码,存储到内存的时候也是用的补码,参与运算的时候到cpu的通用寄存器中的也是补码。
用二进制(0b)存储-27声明如下:
byte b2 = (byte) 0b11100101;
- 1
用八进制(0)存储-27声明如下:
byte b3 = (byte) 0345;
- 1
ps:
-27的补码二进制1110 0101转八进制:从后往前每三位二进制的数为一组,高位不足补零,划分为:011 100 101,八进制为:345(八进制)
用十六进制(0x)存储-27声明如下:
byte b4 = (byte) 0xe5;
- 1
ps:
-27的补码二进制1110 0101转十六进制:从后往前每四位二进制的数为一组,高位不足补零,划分为:1110 0101,十六进制为:e5(十六进制)
2.从byte(字节)的bit(位)层面去理解编码
2.1Unicode编码与UTF-8编码的关系
- Unicode编码:Unicode(统一码、万国码)它是一种理论层面的东西。它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。
- UTF-8编码:是Unicode编码的具体实现,它的UTF-8以字节为单位对Unicode进行编码。
以下是UTF-8的形式:
- 0xxxxxx
说明:它是可变长编码,出现频率较多的字符,如ASCII中的字符,通常是一个字节,这样节省存储空间 - 110xxxxx 10xxx
- 1110xxxx 10xxxxxx 10xxxxxx
说明:汉字通常是3个字节 - 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
ps: xx…x解读:其中一个x对应到Unicode编码中的一bit(位)
UTF-8的特点是对不同范围的字符使用不同长度的编码。对于0x00-0x7F之间的字符,UTF-8编码与ASCII编码完全相同。UTF-8编码的最大长度是4个字节。从上表可以看出,4字节模板有21个x,即可以容纳21位二进制数字。Unicode的最大码位0x10FFFF也只有21位。
2.2用汉字举例,Unicode编码对应到UTF-8编码
我们可以去查喻
这个字,它的Unicode编码为:55bb(十六进制)
把它转换成二进制为: 0101 0101 1011 1011
喻
的Unicode编码为2个字节占16位,对应到UTF-8的时候,我们需要用到上面2.1中提到的1110xxxx 10xxxxxx 10xxxxxx
这种形式,把0101 0101 1011 1011
按位填入到xxx中,即把1110xxxx 10xxxxxx 10xxxxxx
中的x用0101 0101 1011 1011
替换掉。
替换后的结果为:1110
0101 10
010110 10
111011
这就是其UTF-8编码,用十六进制表示为:e596bb(十六进制)
java代码举例:用byte数组定义汉字:
public class StringDemo {
public static void main(String[] args) {
//二进制形式
byte[] bytes = {(byte) 0b11100101,(byte) 0b10010110,(byte) 0b10111011};
//也可以写成十六进制形式
//byte[] bytes = {(byte)0xe5,(byte)0x96,(byte)0xbb};
System.out.println(Arrays.toString(bytes));
System.out.println(binary(bytes,16));
try {
String s = new String(bytes, 0, bytes.length, "UTF-8");
System.out.println(s);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
public static String binary(byte[] bytes,int radix){
return new BigInteger(1,bytes).toString(radix);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
测试输出结果:
文章来源: blog.csdn.net,作者:Mr.Yushiwen,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/MrYushiwen/article/details/119798001
- 点赞
- 收藏
- 关注作者
评论(0)