字节数组和javaBean的相互转换

近期由于物联网的发展,IOT设备对接,成为每个公司必不可少的事情。硬件方面都是采用的MQTT和服务端通讯,这里我们不讲MQTT,因为网上的资料很多,我们来点干货:如何把MQTT的通讯数组(字节数组)转换成我们熟悉的javaBean。

 首先做一下简单的介绍一下。java的数组类型占的字节长度。

byte占一个字节

short占两个字节

int占4四个字节

long占8个字节

以上4个类型,是我们转换中最常用的,根据占用的字节长度来选择对应的类型。举个例子:

根据以上协议,我们定义的javaBean是这样子的。

OK,准备工作完成。接下来上工具类。

ArrayEntityUtil .java

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.dlysapie.mqtt.util;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.util.LinkedList;
import java.util.Queue;

import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;

/**
 * 将byte[]转换为实体
 * 
 * @author baibai
 */
public class ArrayEntityUtil {

	private static Logger LOG = LogManager.getLogger(ArrayEntityUtil.class);

	public static <T> T toEntity(Class<T> entityClass, byte[] data) {
		try {
			Queue<Byte> list = new LinkedList<Byte>();
			for (int i = 0; i < data.length; i++) {
				list.add(data[i]);
			}
			return toEntity(entityClass, list);
		} catch (Exception e) {
			String temp = "";
			for (int i = 0; i < data.length; i++) {
				temp += ((Integer.toString(data[i] & 0xff, 16)) + ",");
			}
			LOG.error("解析数据异常,数据【" + temp + "】", e);
		}
		return null;
	}

	/**
	 * 
	 * @param <T>
	 * @param entityClass 转换目标实体
	 * @param list byte[]队列数据
	 * @return
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @throws InstantiationException
	 */
	private static <T> T toEntity(Class<T> entityClass, Queue<Byte> list)
			throws IllegalArgumentException, IllegalAccessException, InstantiationException {
		Field[] field = entityClass.getDeclaredFields();
		T obj = entityClass.newInstance();
		for (Field f : field) {
			if (!list.isEmpty()) {
				f.setAccessible(true);
				// 1个字节不代替
				if (f.getType().equals(byte.class)) {
					f.setByte(obj, list.poll());
				}
				// 4个字节用long代替
				else if (f.getType().equals(long.class)) {
					if (f.getAnnotation(ByteCount.class).count() == 4) {
						int[] longs = new int[8];
						for (int i = 0; i < 4; i++) {
							longs[i] = list.poll();
						}
						for (int i = 4; i < 8; i++) {
							longs[i] = 0x00;
						}
						f.setLong(obj, DataConUtil.intArray2Long(longs));
					} else {
						int[] longs = new int[8];
						for (int i = 0; i < 8; i++) {
							longs[i] = list.poll();
						}
						f.setLong(obj, DataConUtil.intArray2Long(longs));
					}
				}
				// 8个字节用long代替
				else if (f.getType().equals(Long.class)) {
					int[] longs = new int[8];
					for (int i = 0; i < 8; i++) {
						longs[i] = list.poll();
					}
					f.set(obj, new Long(DataConUtil.intArray2Long(longs)));
				}
				// 2个字节不代替
				else if (f.getType().equals(short.class)) {
					int[] shorts = new int[2];
					for (int i = 0; i < 2; i++) {
						shorts[i] = list.poll();
					}
					f.setShort(obj, DataConUtil.lBytesToShort(shorts));
				}
				// 4个字节float不代替
				else if (f.getType().equals(float.class)) {
					int[] floats = new int[4];
					for (int i = 0; i < 4; i++) {
						floats[i] = list.poll();
					}
					f.setFloat(obj, DataConUtil.lBytesToFloat(floats));
				}
				// 4个字节int不代替
				else if (f.getType().equals(Integer.class) || f.getType().equals(int.class)) {
					int[] ints = new int[4];
					for (int i = 0; i < 4; i++) {
						ints[i] = list.poll();
					}
					f.setInt(obj, DataConUtil.lBytesToInt(ints));
				}
				// 4个字节int不代替
				else if (f.getType().equals(int.class) || f.getType().equals(int.class)) {
					int[] ints = new int[4];
					for (int i = 0; i < 4; i++) {
						ints[i] = list.poll();
					}
					f.setInt(obj, DataConUtil.lBytesToInt(ints));
				} // byte数组转换
				else if ("[B".equals(f.getType().getName())) {
					byte[] d = new byte[f.getAnnotation(ByteCount.class).count()];
					for (int i = 0; i < f.getAnnotation(ByteCount.class).count(); i++) {
						d[i] = list.poll();
					}
					f.set(obj, d);
				}
				// 此if为SocketMode专用
				// else if ("java.util.List".equals(f.getType().getName())) {
				// List<Byte> ls = new ArrayList<Byte>();
				// SocketMode ss = (SocketMode) obj;
				// for (int i = 0; i < ss.getDataLen(); i++) {
				// ls.add(list.poll());
				// }
				// f.set(obj, ls);
				// }
				else if ("java.lang.String".equals(f.getType().getName())) {
					int count = f.getAnnotation(ByteCount.class).count();
					byte[] bs = new byte[count];
					// for (int i = bs.length; i > 0 ; i--) {
					// bs[i-1]=list.poll();
					// }
					for (int i = 0; i < bs.length; i++) {
						bs[i] = list.poll();
					}
					String s = new String(bs);
					f.set(obj, s.trim());
				} else {
					// Log.LOG("未知的数据类型[" + obj.getClass().getName() + "]-" + f.getName(),
					// Level.WARNING,
					// ArrayEntityUtil.class);
				}
			} else {
				return obj;
			}
		}
		return obj;
	}

	public static byte[] toByteArray(Object obj) throws Exception {
		if (obj == null) {
			return new byte[0];
		}
		Queue<Byte> list = toArray(obj);
		byte[] data = new byte[list.size()];
		for (int i = 0; i < data.length; i++) {
			data[i] = list.poll();
		}
		return data;
	}

	public static Queue<Byte> toArray(Object obj)
			throws IllegalArgumentException, IllegalAccessException, UnsupportedEncodingException {
		Queue<Byte> list = new LinkedList<Byte>();
		Field[] field = obj.getClass().getDeclaredFields();
		for (Field f : field) {
			f.setAccessible(true);
			// 1个字节byte
			if (f.getType().equals(byte.class)) {
				list.add(f.getByte(obj));
			} // 4个字节用long代替
			else if (f.getType().equals(long.class)) {
				if (f.getAnnotation(ByteCount.class).count() == 8) {
					for (byte b : DataConUtil.int2Array((Long) f.get(obj), 8)) {
						list.add(b);
					}
				} else if (f.getAnnotation(ByteCount.class).count() == 4) {
					for (byte b : DataConUtil.int2Array(f.getLong(obj), 4)) {
						list.add(b);
					}
				} else {
					for (byte b : DataConUtil.int2Array(f.getLong(obj), 4)) {
						list.add(b);
					}
				}
			} // 2个字节不代替
			else if (f.getType().equals(short.class)) {
				for (byte b : DataConUtil.toLH(f.getShort(obj))) {
					list.add(b);
				}
			} // 4个字节不代替
			else if (f.getType().equals(float.class)) {
				for (byte b : DataConUtil.toLH(f.getFloat(obj))) {
					list.add(b);
				}
			} // 8个字节不代替
			else if (f.getType().equals(Long.class)) {
				for (byte b : DataConUtil.int2Array((Long) f.get(obj), 8)) {
					list.add(b);
				}
			} // 4个字节不代替
			else if (f.getType().equals(Integer.class) || f.getType().equals(int.class)) {
				byte[] data = DataConUtil.toLH((Integer) f.get(obj));
				if (null != f.getAnnotation(ByteCount.class)
						&& f.getAnnotation(ByteCount.class).count() == 2) {
					list.add(data[0]);
					list.add(data[1]);
				} else {
					for (byte b : data) {
						list.add(b);
					}
				}
			} // 4个字节不代替
			else if (f.getType().equals(int.class) || f.getType().equals(int.class)) {
				for (byte b : DataConUtil.toLH((Integer) f.get(obj))) {
					list.add(b);
				}
			} // 字串转换
			else if (f.getType().equals(String.class)) {
				int len = f.getAnnotation(ByteCount.class).count();
				if (f.get(obj) != null) {
					byte[] strs = DataConUtil.stringToBytes((String) f.get(obj));
					if (strs.length <= len) {
						for (int i = 0; i < strs.length; i++) {
							list.add(strs[i]);
						}
						for (int i = 0; i < (len - strs.length); i++) {
							list.add((byte) 0x00);
						}
					} else {
						for (int i = 0; i < len; i++) {
							list.add(strs[i]);
						}
					}
				} else {
					for (int i = 0; i < len; i++) {
						list.add((byte) 0);
					}
				}
			} // int数组转换
			else if ("[I".equals(f.getType().getName())) {
				int len = f.getAnnotation(ByteCount.class).count();
				if (f.get(obj) != null) {
					int[] ds = (int[]) f.get(obj);
					if (ds.length <= len) {
						for (int b : ds) {
							list.add((byte) b);
						}
						for (int i = 0; i < (len - ds.length); i++) {
							list.add((byte) 0);
						}
					} else {
						for (int i = 0; i < len; i++) {
							list.add((byte) ds[i]);
						}
					}
				} else {
					for (int i = 0; i < len; i++) {
						list.add((byte) 0);
					}
				}
			} // byte数组转换
			else if ("[B".equals(f.getType().getName())) {
				if (f.getAnnotation(ByteCount.class) != null) {
					int len = f.getAnnotation(ByteCount.class).count();
					if (f.get(obj) != null) {
						byte[] ds = (byte[]) f.get(obj);

						if (ds.length <= len) {
							for (int b : ds) {
								list.add((byte) b);
							}
							for (int i = 0; i < (len - ds.length); i++) {
								list.add((byte) 0);
							}
						} else {
							for (int i = 0; i < len; i++) {
								list.add((byte) ds[i]);
							}
						}
					} else {
						for (int i = 0; i < len; i++) {
							list.add((byte) 0);
						}
					}
				} else {
					if (f.get(obj) != null) {
						byte[] ds = (byte[]) f.get(obj);
						for (byte b : ds) {
							list.add(b);
						}
					}
				}
			} else {
				// Log.LOG("未知的数据类型[" + obj.getClass().getName() + "]-" + f.getName(),
				// Level.WARNING,
				// ArrayEntityUtil.class);
			}
		}
		return list;
	}

}

2、byteUtil.java

package com.dlysapie.mqtt.util;

/**
 * 
 * byte字节数组转换工具
 * 
 * @author baibai
 * @version 1.0
 */
public class ByteUtil {

	public static byte[] getBytes(short data) {
		byte[] bytes = new byte[2];
		bytes[0] = (byte) (data & 0xff);
		bytes[1] = (byte) ((data & 0xff00) >> 8);
		return bytes;
	}

	public static byte[] getBytes(char data) {
		byte[] bytes = new byte[2];
		bytes[0] = (byte) (data);
		bytes[1] = (byte) (data >> 8);
		return bytes;
	}

	public static byte[] getBytes(int data) {
		byte[] bytes = new byte[4];
		bytes[0] = (byte) (data & 0xff);
		bytes[1] = (byte) ((data & 0xff00) >> 8);
		bytes[2] = (byte) ((data & 0xff0000) >> 16);
		bytes[3] = (byte) ((data & 0xff000000) >> 24);
		return bytes;
	}

	public static byte[] getBytes(long data) {
		byte[] bytes = new byte[8];
		bytes[0] = (byte) (data & 0xff);
		bytes[1] = (byte) ((data >> 8) & 0xff);
		bytes[2] = (byte) ((data >> 16) & 0xff);
		bytes[3] = (byte) ((data >> 24) & 0xff);
		bytes[4] = (byte) ((data >> 32) & 0xff);
		bytes[5] = (byte) ((data >> 40) & 0xff);
		bytes[6] = (byte) ((data >> 48) & 0xff);
		bytes[7] = (byte) ((data >> 56) & 0xff);
		return bytes;
	}

	public static byte[] getBytes(float data) {
		int intBits = Float.floatToIntBits(data);
		return getBytes(intBits);
	}

	public static byte[] getBytes(double data) {
		long intBits = Double.doubleToLongBits(data);
		return getBytes(intBits);
	}

	public static short getShort(byte[] bytes) {
		return (short) ((0xff & bytes[0]) | (0xff00 & (bytes[1] << 8)));
	}

	public static char getChar(byte[] bytes) {
		return (char) ((0xff & bytes[0]) | (0xff00 & (bytes[1] << 8)));
	}

	public static int getInt(byte[] bytes) {
		return (0xff & bytes[0]) | (0xff00 & (bytes[1] << 8)) | (0xff0000 & (bytes[2] << 16))
				| (0xff000000 & (bytes[3] << 24));
	}

	public static long getLong(byte[] bytes) {
		return (0xffL & (long) bytes[0]) | (0xff00L & ((long) bytes[1] << 8))
				| (0xff0000L & ((long) bytes[2] << 16)) | (0xff000000L & ((long) bytes[3] << 24))
				| (0xff00000000L & ((long) bytes[4] << 32))
				| (0xff0000000000L & ((long) bytes[5] << 40))
				| (0xff000000000000L & ((long) bytes[6] << 48))
				| (0xff00000000000000L & ((long) bytes[7] << 56));
	}

	public static float getFloat(byte[] bytes) {
		return Float.intBitsToFloat(getInt(bytes));
	}

	public static double getDouble(byte[] bytes) {
		long l = getLong(bytes);
		return Double.longBitsToDouble(l);
	}
}

3、DataConUtil.java

package com.dlysapie.mqtt.util;

import java.io.UnsupportedEncodingException;

/**
 * 字节数组转换工具
 * 
 * @author baibai
 */
public class DataConUtil {

	/**
	 * 高字节数组转换为float
	 *
	 * @param b byte[]
	 * @return float
	 */
	@SuppressWarnings("static-access")
	public static float hBytesToFloat(byte[] b) {
		int i = 0;
		Float F = new Float(0.0);
		i = ((((b[0] & 0xff) << 8 | (b[1] & 0xff)) << 8) | (b[2] & 0xff)) << 8 | (b[3] & 0xff);
		return F.intBitsToFloat(i);
	}

	/**
	 * 低字节数组转换为float
	 *
	 * @param b byte[]
	 * @return float
	 */
	@SuppressWarnings("static-access")
	public static float lBytesToFloat(byte[] b) {
		int i = 0;
		Float F = new Float(0.0);
		i = ((((b[3] & 0xff) << 8 | (b[2] & 0xff)) << 8) | (b[1] & 0xff)) << 8 | (b[0] & 0xff);
		return F.intBitsToFloat(i);
	}

	/**
	 * 低字节数组转换为float
	 *
	 * @param b byte[]
	 * @return float
	 */
	@SuppressWarnings("static-access")
	public static float lBytesToFloat(int[] b) {
		int i = 0;
		Float F = new Float(0.0);
		i = ((((b[3] & 0xff) << 8 | (b[2] & 0xff)) << 8) | (b[1] & 0xff)) << 8 | (b[0] & 0xff);
		return F.intBitsToFloat(i);
	}

	/**
	 * 将int转为低字节在前,高字节在后的byte数组
	 *
	 * @param n int
	 * @return byte[]
	 */
	public static byte[] toLH(int n) {
		byte[] b = new byte[4];
		b[0] = (byte) (n & 0xff);
		b[1] = (byte) (n >> 8 & 0xff);
		b[2] = (byte) (n >> 16 & 0xff);
		b[3] = (byte) (n >> 24 & 0xff);
		return b;
	}

	/**
	 * 将int转为高字节在前,低字节在后的byte数组
	 *
	 * @param n int
	 * @return byte[]
	 */
	public static byte[] toHH(int n) {
		byte[] b = new byte[4];
		b[3] = (byte) (n & 0xff);
		b[2] = (byte) (n >> 8 & 0xff);
		b[1] = (byte) (n >> 16 & 0xff);
		b[0] = (byte) (n >> 24 & 0xff);
		return b;
	}

	/**
	 * 将short转为低字节在前,高字节在后的byte数组
	 *
	 * @param n short
	 * @return byte[]
	 */
	public static byte[] toLH(short n) {
		byte[] b = new byte[2];
		b[0] = (byte) (n & 0xff);
		b[1] = (byte) (n >> 8 & 0xff);
		return b;
	}

	/**
	 * 将short转为高字节在前,低字节在后的byte数组
	 *
	 * @param n short
	 * @return byte[]
	 */
	public static byte[] toHH(short n) {
		byte[] b = new byte[2];
		b[1] = (byte) (n & 0xff);
		b[0] = (byte) (n >> 8 & 0xff);
		return b;
	}

	/**
	 * 将float转为低字节在前,高字节在后的byte数组
	 */
	public static byte[] toLH(float f) {
		return toLH(Float.floatToRawIntBits(f));
	}

	/**
	 * 将float转为高字节在前,低字节在后的byte数组
	 */
	public static byte[] toHH(float f) {
		return toHH(Float.floatToRawIntBits(f));
	}

	public static byte[] HexString2Bytes(String src) {

		byte[] ret = new byte[src.length() / 2];
		byte[] tmp = src.getBytes();
		for (int i = 0; i < src.length() / 2; i++) {
			ret[i] = uniteBytes(tmp[i * 2], tmp[i * 2 + 1]);
		}
		return ret;
	}

	public static byte uniteBytes(byte src0, byte src1) {
		byte _b0 = Byte.decode("0x" + new String(new byte[] { src0 })).byteValue();
		_b0 = (byte) (_b0 << 4);
		byte _b1 = Byte.decode("0x" + new String(new byte[] { src1 })).byteValue();
		byte ret = (byte) (_b0 ^ _b1);
		return ret;
	}

	/**
	 * 低字节数组到short的转换
	 *
	 * @param b byte[]
	 * @return short
	 */
	public static short lBytesToShort(byte[] b) {
		int s = 0;
		if (b[1] >= 0) {
			s = s + b[1];
		} else {
			s = s + 256 + b[1];
		}
		s = s * 256;
		if (b[0] >= 0) {
			s = s + b[0];
		} else {
			s = s + 256 + b[0];
		}
		short result = (short) s;
		return result;
	}

	/**
	 * 低字节数组到short的转换
	 *
	 * @param b byte[]
	 * @return short
	 */
	public static short lBytesToShort(int[] b) {
		int s = 0;
		if (b[1] >= 0) {
			s = s + b[1];
		} else {
			s = s + 256 + b[1];
		}
		s = s * 256;
		if (b[0] >= 0) {
			s = s + b[0];
		} else {
			s = s + 256 + b[0];
		}
		short result = (short) s;
		return result;
	}

	/**
	 * 将低字节数组转换为int
	 *
	 * @param b byte[]
	 * @return int
	 */
	public static int lBytesToInt(byte[] b) {
		int s = 0;
		for (int i = 0; i < 3; i++) {
			if (b[3 - i] >= 0) {
				s = s + b[3 - i];
			} else {
				s = s + 256 + b[3 - i];
			}
			s = s * 256;
		}
		if (b[0] >= 0) {
			s = s + b[0];
		} else {
			s = s + 256 + b[0];
		}
		return s;
	}

	public static long byteArray2Long(byte[] a) {
		long res = 0L;
		int[] t = new int[8];
		for (int i = 0; i < 8; i++) {
			t[i] = a[7 - i];
		}
		res = t[0] & 0x0ff;
		for (int i = 1; i < 8; i++) {
			res <<= 8;
			res += (t[i] & 0x0ff);
		}
		return res;
	}

	public static long intArray2Long(int[] a) {
		long res = 0L;
		int[] t = new int[8];
		for (int i = 0; i < 8; i++) {
			t[i] = a[7 - i];
		}
		res = t[0] & 0x0ff;
		for (int i = 1; i < 8; i++) {
			res <<= 8;
			res += (t[i] & 0x0ff);
		}
		return res;
	}

	/**
	 * 将低字节数组转换为int
	 *
	 * @param b byte[]
	 * @return int
	 */
	public static int lBytesToInt(int[] b) {
		int s = 0;
		for (int i = 0; i < 3; i++) {
			if (b[3 - i] >= 0) {
				s = s + b[3 - i];
			} else {
				s = s + 256 + b[3 - i];
			}
			s = s * 256;
		}
		if (b[0] >= 0) {
			s = s + b[0];
		} else {
			s = s + 256 + b[0];
		}
		return s;
	}

	/**
	 * 此方法将参数i 转换为 num bytes的byte 数组 (小端模式)
	 *
	 * @param i
	 * @param num
	 * @return
	 */
	public static byte[] int2Array(Long i, int num) {
		byte[] a = new byte[num];
		for (int j = 0; j < a.length; j++) {
			a[j] = (byte) (i & 0xff);
			i >>= 8;
		}
		byte[] cc = new byte[a.length];
		for (int x = 0; x < a.length; x++) {
			cc[x] = a[x];
		}
		return cc;
	}

	/**
	 * 将String转为byte数组
	 */
	public static byte[] stringToBytes(String s, int length) {
		while (s.getBytes().length < length) {
			s += " ";
		}
		return s.getBytes();
	}

	/**
	 * 将字符串转换为byte数组
	 *
	 * @param s String
	 * @return byte[]
	 */
	public static byte[] stringToBytes(String s) throws UnsupportedEncodingException {
		if (null == s) {
			s = "";
		}
		return s.getBytes("GB2312");
	}

	public static byte[] stringToBytes1(String s) throws UnsupportedEncodingException {
		if (null == s) {
			s = "";
		}
		return s.getBytes("UTF-8");
	}

}

然后就可以直接转换啦

	public void exe(String topic, String content) {
		byte[] con = Base64.decode(content);
		System.out.println("==" + Arrays.toString(con));

		// 固定头
		byte[] startByte = new byte[2];
		System.arraycopy(con, 0, startByte, 0, 2);
		if (startByte[0] != -46 || startByte[1] != -91) {
			LOG.warn("数组错误:startByte=" + Arrays.toString(startByte));
			return;
		}

		// 校验和
		byte[] chByte = new byte[1];
		System.arraycopy(con, 2, chByte, 0, 1);

		// 命令
		byte[] cmdByte = new byte[1];
		System.arraycopy(con, 3, cmdByte, 0, 1);

		// 数据
		int len = con.length;
		byte[] dataByte = new byte[len - 4];
		System.arraycopy(con, 4, dataByte, 0, (len - 4));
		System.out.print(Arrays.toString(dataByte));
		DataBean dataBean = ArrayEntityUtil.toEntity(DataBean.class, dataByte);
		try {
			System.out.println(Arrays.toString(ArrayEntityUtil.toByteArray(dataBean)));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

到这里,字节数组和javaBean的相互转换就完成了,大家可以根据自己的需求,做调整。

但是有时候我们需要自定义字节长度,这里就需要我们用到自定义的注解了

@byteCount

package com.dlysapie.mqtt.util;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 
 * @author baibai
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD })
public @interface ByteCount {
	int count();
}

比如:我们需要一个32个字节长度

	@ByteCount(count = 32)
	private String code; // 设备编码

好了,到这里,基本上可以满足大部分的需求了,有什么不对的地方,欢迎大家指出更正,大家还有什么好的方法,也欢迎大家来留言。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木小百99

听说打赏的人都发财了

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值