字節數組和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; // 設備編碼

好了,到這裏,基本上可以滿足大部分的需求了,有什麼不對的地方,歡迎大家指出更正,大家還有什麼好的方法,也歡迎大家來留言。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章