package com.tanruyu.jvm.decompile;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;
/**
* 将字节数组 与 数字互转 工具类
*
* 本篇代码 工具实现,将数字转化 成byte [] 或者 将byte [] 转换成 数字,采用的是 little-endian byte order(低位优先字节顺序) 模式
* 而java nio 的 ByteBuffer 默认采用了 big-endian byte order (高位优先字节顺序),如果要改变nio 默认方法,可以在调用方法之前,
* 调用 public final ByteBuffer order(ByteOrder bo) 方法,传递 ByteOrder.LITTLE_ENDIAN
*
* @ClassName: ByteArrTransformLiteral
* @author ruyu.tan
* @date 2019年1月14日 上午10:51:03
* @version V1.0
*
*/
public class ByteArrTransformLiteralUtils {
/**
* 方法描述: 将字节数组转换成字节数字
* @Title: transformByte
* @date 2019年1月15日 下午2:44:59
* @author ruyu.tan
* @modifier
* @modifydate
* @param b
* @return
*/
public static byte transformByte(byte [] b) {
if(b == null || b.length != 1) {
throw new RuntimeException("入参错误");
}
return b[0];
}
/**
* 方法描述: 将byte 数组(2个字节) 转换为 short
* short 结构二进制表示为 :
* 0000 0000 0000 0000
* 8 个bit 组成 一个字节 ,一个short 由2个字节组成
* 1、通过 &(与运算) 0xFF ,是获取一个数字的最低位字节,(这一步可以省略)
* 2、字节数组中,根据数组下标索引分别进行对 数组中每一个字节进行相应的左移操作,操作位数是以1个字节为单位进行
*
* (eg , 就好像 10进制中 123 -》 对应数组是 [1,2,3] --> 1*10^2 + 2*10^1 + 3*10^0 = 123 )
* 3、再通过 | 或运算,将不同们之间的字节进行相加,得到最终的数字
*
* @Title: transformShort
* @date 2019年1月15日 上午11:31:57
* @author ruyu.tan
* @modifier
* @modifydate
* @param b
* @return
*/
public static short transformShort(byte [] b) {
//进行校验字节数组是否合法
if(b == null || b.length != 2) {
throw new RuntimeException("入参错误");
}
// 用于存放 各个字节数组中对应 short 的低位 和 高位
short [] temp = new short[b.length];
for (int i = 0; i<b.length ;i++) {
temp [i] = (short) (b[i] & 0xff);
}
//从 第二个字节开始 ,根据字节的下标分别进行左移运算,左移 8
for(int j = 1;j<temp.length;j++) {
temp [j] = (short) (temp[j] << (8*j));// 等价于 ==》 temp[j] << (8*i) ==> temp[j] * 2^(8*i)
}
short result = 0;
//将每个字节位进行 或运算
for(int i = 1;i<temp.length;i++) {
if(i == 1) {
result = temp[0];
}
result = (short) (result | temp[i]);
}
return result;
}
/**
* 方法描述: 将byte 数组(4个字节) 转化为 int 类型
* @Title: transformInt
* @date 2019年1月15日 下午2:39:36
* @author ruyu.tan
* @modifier
* @modifydate
* @param b
* @return
*/
public static int transformInt(byte [] b) {
if(b == null || b.length != 4) {
throw new RuntimeException("入参错误");
}
int [] temp = new int[b.length];
for (int i = 0; i<b.length ;i++) {
temp [i] = b[i] & 0xff;
}
//从 第二个字节开始 ,根据字节的下标分别进行左移运算,分别是 左移 8 ,左移16,左移 24
for (int j = 1 ; j<temp.length; j++) {
temp [j] = temp[j] << (8*j);
}
int result = 0;
//将每个字节位进行 或运算
for(int i = 1;i<temp.length;i++) {
if(i == 1) {
result = temp[0];
}
result = result | temp[i];
}
return result;
}
/**
* 方法描述: 将byte 数组(8个字节) 转化为 long 类型
* @Title: transformLong
* @date 2019年1月15日 下午2:41:50
* @author ruyu.tan
* @modifier
* @modifydate
* @param b
* @return
*/
public static long transformLong (byte [] b) {
if(b == null || b.length != 8) {
throw new RuntimeException("入参错误");
}
long [] temp = new long[b.length];
for (int i = 0; i<b.length ;i++) {
temp [i] = b[i] & 0xff;
}
//从 第二个字节开始 ,根据字节的下标分别进行左移运算,分别是 左移 8 ,左移16,左移 24,左移32,左移40,左移 48,左移 56
for (int j = 1 ; j<temp.length; j++) {
temp [j] = temp[j] << (8*j);
}
long result = 0;
//将每个字节位进行 或运算
for(int i = 1;i<temp.length;i++) {
if(i == 1) {
result = temp[0];
}
result = result | temp[i];
}
return result;
}
public static byte[] transformBytes(byte number) {
return transformByteArr(number);
}
public static byte[] transformBytes(short number) {
return transformByteArr(number);
}
public static byte[] transformBytes(int number) {
return transformByteArr(number);
}
public static byte[] transformBytes(long number) {
return transformByteArr(number);
}
private static byte[] transformByteArr(Number number) {
if(number == null) {
throw new RuntimeException("参数非法");
}
int length = 0;
byte[] b = null;
if (number instanceof Byte) {
length = 1;
return new byte[] {number.byteValue()};
} else if (number instanceof Short) {
length = 2;
} else if (number instanceof Integer) {
length = 4;
} else if (number instanceof Long) {
length = 8;
} else {
throw new RuntimeException("参数非法");
}
long temp = number.longValue();
b = new byte[length];
for (int i = 0; i < b.length; i++) {
// 以下代码等价于 b[i] = new Integer(temp & 0xff).byteValue();
b[i] = (byte) (temp & 0xff);//获取 temp 中最低位 的8个字节 ,直接存入到字节数组中
// 然后再将当前的数字 进行右移8位,重新赋值
temp = temp >> 8;// 向右移8位
}
return b;
}
/**
* 以下方法采用了 java nio 的方式实现,但是它的结果与上面获取到了字节数组中的元素位置刚好相反 ,原因是nio 默认采用了 big-endian byte order (高位优先字节顺序),
* 如果想结果与作者上面方法一致,直接将ByteBuffer实例调用 order(ByteOrder order) 方法进行设置,eg. byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
*/
public static byte[] longFormatBytes(long number) {
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
// byteBuffer.order(ByteOrder.BIG_ENDIAN); //默认采用了 高位优先字节顺序
byteBuffer.putLong(number);
byteBuffer.flip();
byte b[] = new byte[8];
byteBuffer.get(b);
return b;
}
public static long bytes2Long(byte [] b) {
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
byteBuffer.put(b);
byteBuffer.flip();
return byteBuffer.getLong();
}
public static byte[] intFormatBytes(int number) {
ByteBuffer byteBuffer = ByteBuffer.allocate(4);
byteBuffer.putInt(number);
byteBuffer.flip();
byte b[] = new byte[4];
byteBuffer.get(b);
return b;
}
public static int bytes2Int(byte [] b) {
ByteBuffer byteBuffer = ByteBuffer.allocate(4);
byteBuffer.put(b);
byteBuffer.flip();
return byteBuffer.getInt();
}
public static byte[] shortFormatBytes(short number) {
ByteBuffer byteBuffer = ByteBuffer.allocate(2);
byteBuffer.putShort(number);
byteBuffer.flip();
byte b[] = new byte[2];
byteBuffer.get(b);
return b;
}
public static short bytes2Short(byte [] b) {
ByteBuffer byteBuffer = ByteBuffer.allocate(2);
byteBuffer.put(b);
byteBuffer.flip();
return byteBuffer.getShort();
}
public static void main(String[] args) {
System.out.println("采用 nio 得出结果");
byte [] tt = longFormatBytes(1078042447871l);
System.out.println(Arrays.toString(tt));
System.out.println(bytes2Long(tt));
System.out.println(transformLong(tt));
byte [] ii = intFormatBytes(5656575);
System.out.println(Arrays.toString(ii));
System.out.println(bytes2Int(ii));
byte [] ss = shortFormatBytes((short)596);
System.out.println(Arrays.toString(ss));
System.out.println(bytes2Short(ss));
System.out.println();
System.out.println("笔者自己方法得出的结果");
byte [] b1 = new byte[] {127};
byte [] b2 = new byte[] {84, 2};
byte [] b3 = new byte[] {-1, 79, 86, 0};
byte [] b33 = new byte[] {-1, 79, 86, 0};
byte [] b4 = new byte[] {-1, 79, 86, 0, -5, 0, 0, 0};
byte [] b44 = new byte[] {-1, 79, 86, 0, -5, 0, 0, 0};
byte byte1 = transformByte(b1);
short s1 = transformShort(b2);
int i1 = transformInt(b3);
int i2 = transformInt(b33);
long l1 = transformLong(b4);
long l2 = transformLong(b44);
System.out.println("数组 " + Arrays.toString(b1) + " , 对应的数字是:" + byte1);
System.out.println("数组 " + Arrays.toString(b2) + " , 对应的数字是:" + s1);
System.out.println("数组 " + Arrays.toString(b3) + " , 对应的数字是:" + i1);
System.out.println("数组 " + Arrays.toString(b33) + " , 对应的数字是:" + i2);
System.out.println("**************************");
System.out.println();
System.out.println("数组 " + Arrays.toString(b4) + " , 对应的数字是:" + l1);
System.out.println("数组 " + Arrays.toString(b44) + " , 对应的数字是:" + l2);
System.out.println("**************************");
System.out.println();
System.out.println("数字 :"+ byte1 + "对应的字节数组是:" + Arrays.toString(transformBytes(byte1)));
System.out.println("数字 :"+ s1 + " 对应的字节数组是:" + Arrays.toString(transformBytes(s1)));
System.out.println("数字 :"+ i1 + " 对应的字节数组是:" + Arrays.toString(transformBytes(i1)));
System.out.println("数字 :"+ i2 + " 对应的字节数组是:" + Arrays.toString(transformBytes(i2)));
System.out.println("数字 :"+ l1 + " 对应的字节数组是:" + Arrays.toString(transformBytes(l1)));
System.out.println("数字 :"+ l2 + " 对应的字节数组是:" + Arrays.toString(transformBytes(1078042447871l)));
}
}
在上面的代码中,如果有读者不清楚, 与运算 (&) 、或运算 (|)、左移(<<)、右移(>>)所表示的含义,可以看一下作者的另一篇博文:https://blog.csdn.net/u012149894/article/details/86521476
还在关于二进制的一些基本概念:https://blog.csdn.net/u012149894/article/details/86496780