在接触modbus报文过程中,发现报文中有的数值的表示方式为4字节浮点型;如下是我对四字节浮点型相关概念的理解与转换代码;
相关概念
以下仅是我个人对概念的理解,存在一点的不足和偏差;若想理解规范的概念请自查。
小终端与大终端
在了解大终端、小终端之前需了解高低位;高低位是以权位来区别的;
数值:12 高位:1 低位:2 原因:十位的权重高于个位的权重
大终端: 高字节在前,ABCD
小终端: 低字节在前,DCBA
eg:大终端 3E 56 04 19 小终端 19 04 56 3E
转换代码
十六进制字符串转float类型有两步,第一:将十六进制字符串转为字节数组;
第二:将字节数组转为float类型(如下两种方法);
/** 用于解析四字节转float
* 何处调用:雷达流量计报文解析工具
* */
public class HexToFloat {
/**小终端 十六进制 四字节转float*/
public static Float smallHextoFloat(String s) throws IOException {//s 为报文中截取的对应值 eg:19 04 56 3E 且数值的表示方式为四字节浮点型、小终端低字节在前
String s1 = s.replace(" ", "");//将字符串中的空格去除
String s2 = s.substring(6,8) + s.substring(4,6) + s.substring(2,4) + s.substring(0,2);/*将小终端换为大终端*/
return bigHextoFloat(s2);
}
/**大终端 十六进制 四字节转float*/
public static Float bigHextoFloat(String s) throws IOException {//s 为报文中截取的对应值 eg:3E 56 04 19 且数值的表示方式为四字节浮点型、大终端高字节在前
String src = s.replace(" ", "");//将字符串中的空格去除
/**将十六进制字符串转为字节数组*/
byte[] ret = new byte[src.length() / 2];
byte[] tmp = src.getBytes();
for (int i = 0; i < (tmp.length / 2); i++) {
ret[i] = uniteBytes(tmp[i * 2], tmp[i * 2 + 1]);
}
// 流输入,适用于ME/SE环境
/**将字节数组转为float类型数据 第一种*///默认大端数,如果小端数,可以先翻转数组
DataInputStream dis=new DataInputStream(new ByteArrayInputStream(ret));
float f=dis.readFloat();
dis.close();
return f;
}
/**
* 将十六进制字符串转为字节数组*/
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;
}
/**
* 将字节数组转换成16进制字符串 第二种
* @param bytes
* @return
*/
public static String bytes2BinaryStr(byte[] bytes){
StringBuffer binaryStr = new StringBuffer();
for(int i=0;i<bytes.length;i++){
String str = Integer.toBinaryString((bytes[i] & 0xFF) + 0x100).substring(1);
binaryStr.append(str);
}
return binaryStr.toString();
}
}