近期由於物聯網的發展,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; // 設備編碼
好了,到這裏,基本上可以滿足大部分的需求了,有什麼不對的地方,歡迎大家指出更正,大家還有什麼好的方法,也歡迎大家來留言。