最近做canal 其中parse 模块的driver 里面二进制 ,十六进制,io流转换,不是很懂,就亲自己实践一下:
1)概念知识:
一个数在计算机中的二进制表示形式, 叫做这个数的机器数。机器数是带符号的,在计算机用一个数的最高位存放符号, 正数为0, 负数为1
- 二进制: o,1, 满2进1,以0b/B开头
- 十进制: 0-9 满10进1,平常通用。
- 八进制:0-7,满8进1,以0开头
- 十六进制:0-9 a-f 满16进1, 以0x开头,不分大小写。
比如,十进制中的数 +3 ,计算机字长为8位,转换成二进制就是00000011。如果是 -3 ,就是 10000011 ,那么,这里的 00000011 和 10000011 就是机器数。
因为第一位是符号位,所以机器数的形式值就不等于真正的数值。例如上面的有符号数 10000011,其最高位1代表负,其真正数值是 -3 而 不是形式值131(10000011转换成十进制等于131)。所以,为区别起见,将带符号位的机器数对应的真正数值称为机器数的真值。
源码:原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值. 比如如果是8位二进制:
反码:正数的反码是其本身 负数的反码是在其原码的基础上, 符号位不变,其余各个位取反.
补码: 正数的补码就是其本身 负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)
总结:正数 :源码,反码,补码都是本身
负数: 反码为符号位不变,其余取反,补码为反码+1
先看下如下代码:
public static void main(String[] args) {
int data=2202;
ByteArrayOutputStream out = new ByteArrayOutputStream();
out.write((byte) (data & 0xFF));
out.write((byte) (data >>> 8));
out.write((byte) (data >>> 16));
out.write((byte) (data >>> 24));
System.out.println("data的二进制:"+Integer.toBinaryString(data));
System.out.println("=======================================");
int a =data & 0xFF;
System.out.println("a的二进制:"+Integer.toBinaryString(a));
}
result:
data的二进制:100010011010
=======================================
a的二进制:10011010
2)底层如何转换
buf为31个默认初始0,count为0
2.1)data&0xff
看下如何转换的:
2.1)采用二进制 转换
data的二进制:100010011010
0xff的二进制: 11111111
结果为: 000010011010 如上a的值:
但是a的二进制是10011010 那debug 为何为-102?
以上运算,我们计算的结果为计算机的逻辑运算,但是计算机存放二进制,是以补码存放的, 所以 10011010的补码为其反码取反+1 也就是:
1001 1010
取反:符号位不变
1110 0101
+1
1110 0110
看下1110 0110 的十进制是多少:
108 64 32 16 8 4 2 1
1 1 0 0 1 1 0
结果为:
-102