Java中对字节的详解 郝伟 2021/06/04 [TOC]
1. 1 简介
在信息安全领域,对字节的操作非常频繁,所以本文对字节操作的相关内容进行详细介绍。
2. 2 基本定义
1字节等于8个位,是计算机中数据的最基础的组成单元。在Java中,没有无符号数,所以1个字节的表示范围是 -128 ~ 127。
3. 3 初始化
二进制有初始化有三种方法:
- 十进制数直接赋值,如
byte b = 100; - 使用十六进制表示, 如
byte b = 0xff; - 使用二进制表示, 如
byte b = 0b10001000;所以在进行字节操作的时候就就会有这样的问题。
注意:使用任何超出字节值域(即-128~127)的赋值都会会报 java.lang.Error: cannot convert from int to byte 错误。
4. 4 常用运算
4.1. 4.1 四则运算
节点变量支持常规的四则运算,但是需要注意一点就是返回的数据类型都是 Integer 所以需要进行转换。
先看这样的一个示例,以下代码实现两个字节的四则运算:
public static void test1() {
byte a = 0x7f;
byte b = 0x3;
var c1 = a + b;
var c2 = a - b;
var c3 = a * b;
var c4 = a / b;
System.out.println("c1 = " + c1 + ", " + getClassName(c1));
System.out.println("c2 = " + c2 + ", " + getClassName(c2));
System.out.println("c3 = " + c3 + ", " + getClassName(c3));
System.out.println("c4 = " + c4 + ", " + getClassName(c4));
}
public static String getClassName(Object o) {
return o.getClass().getSimpleName();
}
输出结果为:
c1 = 130, Integer
c2 = 124, Integer
c3 = 381, Integer
c4 = 42, Integer
由此可见,字节运算的底层实现是将字节型转为整型,再进行运算,然后返回一个整型。这样在理解上就比较容易,对结果也好评估。
4.2. 4.2 特殊运算
4.2.1. 4.2.1 或运算
或运算是最基本的逻辑运算之一,可以实现字节中每个位与位的运算,请看以下示例:
public static void test3() {
System.out.println("或运算");
System.out.println(0b0 | 0b0);
System.out.println(0b1 | 0b0);
System.out.println(0b1 | 0b1);
System.out.println(0b01010101 | 0b10101010);
}
输出结果如下,输出分别是由低到高取得每一位的值,结果与预期一致。
或运算
0
1
1
255
4.2.2. 4.2.2 或运算
与运算是最基本的逻辑运算之一,可以实现字节中每个位与位的运算,请看以下示例:
public static void test2() {
System.out.println("变量与常量异或");
byte b = (byte) 0b11111111;
System.out.println(b & 0b00000001);
System.out.println(b & 0b00000010);
System.out.println(b & 0b00000100);
System.out.println(b & 0b00001000);
System.out.println(b & 0b00010000);
System.out.println(b & 0b00100000);
System.out.println(b & 0b01000000);
System.out.println(b & 0b10000000);
}
输出结果如下,输出分别是由低到高取得每一位的值,结果与预期一致。
变量与常量异或
1
2
4
8
16
32
64
128
4.2.3. 4.2.3 非运算
与运算是最基本的逻辑运算之一,可以实现字节中每个位与位的运算,请看以下示例:
public static void test4() {
System.out.println("非运算");
byte b1 = (byte) 0b00000000;
byte b2 = (byte) 0b11111111;
byte b3 = (byte) 0b01010101;
System.out.println(byteToString(b1) + " --取反--> " + byteToString((byte)~b1));
System.out.println(byteToString(b2) + " --取反--> " + byteToString((byte)~b2));
System.out.println(byteToString(b3) + " --取反--> " + byteToString((byte)~b3));
}
输出结果如下,输出分别是由低到高取得每一位的值,结果与预期一致。
非运算
00000000 --取反--> 11111111
11111111 --取反--> 00000000
01010101 --取反--> 10101010
4.2.4. 4.2.4 异或运算
异或顾名思义,两个位不相同时为1,相同时为0,请看下面的示例。
public static void test5() {
System.out.println("异或运算");
byte b1 = (byte) 0b00000000;
byte b2 = (byte) 0b11111111;
byte b3 = (byte) 0b01010101;
xor(b1, b2);
xor(b2, b3);
xor(b3, b1);
}
public static void xor(byte b1, byte b2) {
var bstr1 = byteToString(b1);
var bstr2 = byteToString(b2);
var bstr3 = byteToString((byte)(b1^b2));
System.out.printf("%s ^ %s --> %s\n", bstr1, bstr2, bstr3);
}
输出结果为:
异或运算
00000000 & 11111111 --> 11111111
11111111 & 01010101 --> 10101010
01010101 & 00000000 --> 01010101
实际上,与异或相对应的还是同或运行,即相同时为1,不同时为0,但是在Java中没有实现。我们可以对异或取反即可。
5. 5 附录
5.1. 5.1 几个引用到的函数
public static String byteToString(byte b) {
int datalen = 8;
String[] data = new String[datalen];
for (int i = 0, w = 1; i < datalen; i++, w *= 2)
data[datalen - i - 1] = (b & w) > 0 ? "1" : "0";
return String.join("", data);
}
public static String intToString(int b) {
int datalen = 32;
String[] data = new String[datalen];
for (int i = 0, w = 1; i < datalen; i++, w *= 2)
data[datalen - i - 1] = (b & w) > 0 ? "1" : "0";
return String.join("", data);
}
5.2. 5.2 所有源代码
public class ByteOperationDemo {
public static void main(String[] args) {
test0();
test1();
test2();
test3();
test4();
test5();
}
public static void test5() {
System.out.println("异或运算");
byte b1 = (byte) 0b00000000;
byte b2 = (byte) 0b11111111;
byte b3 = (byte) 0b01010101;
xor(b1, b2);
xor(b2, b3);
xor(b3, b1);
}
public static void xor(byte b1, byte b2) {
var bstr1 = byteToString(b1);
var bstr2 = byteToString(b2);
var bstr3 = byteToString((byte)(b1^b2));
System.out.printf("%s ^ %s --> %s\n", bstr1, bstr2, bstr3);
}
public static void test4() {
System.out.println("非运算");
byte b1 = (byte) 0b00000000;
byte b2 = (byte) 0b11111111;
byte b3 = (byte) 0b01010101;
System.out.println(byteToString(b1) + " --取反--> " + byteToString((byte)~b1));
System.out.println(byteToString(b2) + " --取反--> " + byteToString((byte)~b2));
System.out.println(byteToString(b3) + " --取反--> " + byteToString((byte)~b3));
}
public static void test3() {
System.out.println("或运算");
System.out.println(0b0 | 0b0);
System.out.println(0b1 | 0b0);
System.out.println(0b1 | 0b1);
System.out.println(0b01010101 | 0b10101010);
}
public static void test2() {
System.out.println("变量与常量异或");
byte b = (byte) 0b11111111;
System.out.println(b & 0b00000001);
System.out.println(b & 0b00000010);
System.out.println(b & 0b00000100);
System.out.println(b & 0b00001000);
System.out.println(b & 0b00010000);
System.out.println(b & 0b00100000);
System.out.println(b & 0b01000000);
System.out.println(b & 0b10000000);
}
public static void test1() {
byte a = 0x7f;
byte b = 0x3;
var c1 = a + b;
var c2 = a - b;
var c3 = a * b;
var c4 = a / b;
System.out.println("c1 = " + c1 + ", " + getClassName(c1));
System.out.println("c2 = " + c2 + ", " + getClassName(c2));
System.out.println("c3 = " + c3 + ", " + getClassName(c3));
System.out.println("c4 = " + c4 + ", " + getClassName(c4));
}
public static void test0() {
for (int i = 0; i < 256; i++)
System.out.println((i & 0xff) + ": " + byteToString((byte) i));
}
public static String getClassName(Object o) {
return o.getClass().getSimpleName();
}
public static void showType(Object o) {
//System.out.println(o instanceof Integer);
//System.out.println(o.getClass().getName());
System.out.println(o.getClass().getSimpleName());
}
public static String byteToString(byte b) {
int datalen = 8;
String[] data = new String[datalen];
for (int i = 0, w = 1; i < datalen; i++, w *= 2)
data[datalen - i - 1] = (b & w) > 0 ? "1" : "0";
return String.join("", data);
}
public static String intToString(int b) {
int datalen = 32;
String[] data = new String[datalen];
for (int i = 0, w = 1; i < datalen; i++, w *= 2)
data[datalen - i - 1] = (b & w) > 0 ? "1" : "0";
return String.join("", data);
}
}