近期由于物联网的发展,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; // 设备编码
好了,到这里,基本上可以满足大部分的需求了,有什么不对的地方,欢迎大家指出更正,大家还有什么好的方法,也欢迎大家来留言。