java中关于byte,short,int,long 与 byte[] 数组的转换原理

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值