fix bytesToFloat bug

This commit is contained in:
looly
2021-12-12 11:43:56 +08:00
parent a9bd7c3bb4
commit 60901d5815
5 changed files with 193 additions and 57 deletions

View File

@@ -8,6 +8,7 @@
### 🐣新特性
### 🐞Bug修复
* 【core 】 LineReadWatcher#onModify文件清空判断问题issue#2013@Github
* 【core 】 修复4位bytes转换float问题issue#I4M0E4@Github
-------------------------------------------------------------------------------------------------------------
# 5.7.17 (2021-12-09)

View File

@@ -54,13 +54,40 @@ public class NumberConverter extends AbstractConverter<Number> {
this.targetType = (null == clazz) ? Number.class : clazz;
}
@Override
@SuppressWarnings("unchecked")
public Class<Number> getTargetType() {
return (Class<Number>) this.targetType;
}
@Override
protected Number convertInternal(Object value) {
return convert(value, this.targetType, this::convertToStr);
}
@Override
protected String convertToStr(Object value) {
String result = StrUtil.trim(super.convertToStr(value));
if (StrUtil.isNotEmpty(result)) {
final char c = Character.toUpperCase(result.charAt(result.length() - 1));
if (c == 'D' || c == 'L' || c == 'F') {
// 类型标识形式例如123.6D
return StrUtil.subPre(result, -1);
}
}
return result;
}
/**
* 转换对象为数字
* 转换对象为数字,支持的对象包括:
* <ul>
* <li>Number对象</li>
* <li>Boolean</li>
* <li>byte[]</li>
* <li>String</li>
* </ul>
*
*
* @param value 对象值
* @param targetType 目标的数字类型
@@ -68,12 +95,17 @@ public class NumberConverter extends AbstractConverter<Number> {
* @return 转换后的数字
* @since 5.5.0
*/
protected static Number convert(Object value, Class<?> targetType, Function<Object, String> toStrFunc) {
protected static Number convert(Object value, Class<? extends Number> targetType, Function<Object, String> toStrFunc) {
// 枚举转换为数字默认为其顺序
if (value instanceof Enum) {
return convert(((Enum<?>) value).ordinal(), targetType, toStrFunc);
}
// since 5.7.18
if(value instanceof byte[]){
return ByteUtil.bytesToNumber((byte[])value, targetType, ByteUtil.DEFAULT_ORDER);
}
if (Byte.class == targetType) {
if (value instanceof Number) {
return ((Number) value).byteValue();
@@ -91,8 +123,6 @@ public class NumberConverter extends AbstractConverter<Number> {
return ((Number) value).shortValue();
} else if (value instanceof Boolean) {
return BooleanUtil.toShortObj((Boolean) value);
} else if (value instanceof byte[]){
return ByteUtil.bytesToShort((byte[]) value);
}
final String valueStr = toStrFunc.apply((value));
try{
@@ -111,17 +141,13 @@ public class NumberConverter extends AbstractConverter<Number> {
return (int) ((Calendar) value).getTimeInMillis();
} else if (value instanceof TemporalAccessor) {
return (int) DateUtil.toInstant((TemporalAccessor) value).toEpochMilli();
} else if (value instanceof byte[]){
return ByteUtil.bytesToInt((byte[]) value);
}
final String valueStr = toStrFunc.apply((value));
return StrUtil.isBlank(valueStr) ? null : NumberUtil.parseInt(valueStr);
} else if (AtomicInteger.class == targetType) {
final Number number = convert(value, Integer.class, toStrFunc);
if (null != number) {
final AtomicInteger intValue = new AtomicInteger();
intValue.set(number.intValue());
return intValue;
return new AtomicInteger(number.intValue());
}
} else if (Long.class == targetType) {
if (value instanceof Number) {
@@ -134,17 +160,13 @@ public class NumberConverter extends AbstractConverter<Number> {
return ((Calendar) value).getTimeInMillis();
} else if (value instanceof TemporalAccessor) {
return DateUtil.toInstant((TemporalAccessor) value).toEpochMilli();
}else if (value instanceof byte[]){
return ByteUtil.bytesToLong((byte[]) value);
}
final String valueStr = toStrFunc.apply((value));
return StrUtil.isBlank(valueStr) ? null : NumberUtil.parseLong(valueStr);
} else if (AtomicLong.class == targetType) {
final Number number = convert(value, Long.class, toStrFunc);
if (null != number) {
final AtomicLong longValue = new AtomicLong();
longValue.set(number.longValue());
return longValue;
return new AtomicLong(number.longValue());
}
} else if (LongAdder.class == targetType) {
//jdk8 新增
@@ -159,8 +181,6 @@ public class NumberConverter extends AbstractConverter<Number> {
return ((Number) value).floatValue();
} else if (value instanceof Boolean) {
return BooleanUtil.toFloatObj((Boolean) value);
} else if (value instanceof byte[]){
return (float)ByteUtil.bytesToDouble((byte[]) value);
}
final String valueStr = toStrFunc.apply((value));
return StrUtil.isBlank(valueStr) ? null : NumberUtil.parseFloat(valueStr);
@@ -169,8 +189,6 @@ public class NumberConverter extends AbstractConverter<Number> {
return ((Number) value).doubleValue();
} else if (value instanceof Boolean) {
return BooleanUtil.toDoubleObj((Boolean) value);
} else if (value instanceof byte[]){
return ByteUtil.bytesToDouble((byte[]) value);
}
final String valueStr = toStrFunc.apply((value));
return StrUtil.isBlank(valueStr) ? null : NumberUtil.parseDouble(valueStr);
@@ -212,9 +230,7 @@ public class NumberConverter extends AbstractConverter<Number> {
if (value instanceof Number) {
return NumberUtil.toBigDecimal((Number) value);
} else if (value instanceof Boolean) {
return new BigDecimal((boolean) value ? 1 : 0);
} else if (value instanceof byte[]){
return NumberUtil.toBigDecimal(ByteUtil.bytesToDouble((byte[]) value));
return ((boolean) value) ? BigDecimal.ONE : BigDecimal.ZERO;
}
//对于Double类型先要转换为String避免精度问题
@@ -234,31 +250,9 @@ public class NumberConverter extends AbstractConverter<Number> {
if (value instanceof Long) {
return BigInteger.valueOf((Long) value);
} else if (value instanceof Boolean) {
return BigInteger.valueOf((boolean) value ? 1 : 0);
} else if (value instanceof byte[]){
return BigInteger.valueOf(ByteUtil.bytesToLong((byte[]) value));
return (boolean) value ? BigInteger.ONE : BigInteger.ZERO;
}
return NumberUtil.toBigInteger(toStrFunc.apply(value));
}
@Override
protected String convertToStr(Object value) {
String result = StrUtil.trim(super.convertToStr(value));
if (StrUtil.isNotEmpty(result)) {
final char c = Character.toUpperCase(result.charAt(result.length() - 1));
if (c == 'D' || c == 'L' || c == 'F') {
// 类型标识形式例如123.6D
return StrUtil.subPre(result, -1);
}
}
return result;
}
@Override
@SuppressWarnings("unchecked")
public Class<Number> getTargetType() {
return (Class<Number>) this.targetType;
}
}

View File

@@ -1,6 +1,12 @@
package cn.hutool.core.util;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.ByteOrder;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.DoubleAdder;
import java.util.concurrent.atomic.LongAdder;
/**
* 对数字和字节进行转换。<br>
@@ -21,6 +27,8 @@ import java.nio.ByteOrder;
*/
public class ByteUtil {
public static ByteOrder DEFAULT_ORDER = ByteOrder.LITTLE_ENDIAN;
/**
* int转byte
*
@@ -51,14 +59,14 @@ public class ByteUtil {
* @return short值
*/
public static short bytesToShort(byte[] bytes) {
return bytesToShort(bytes, ByteOrder.LITTLE_ENDIAN);
return bytesToShort(bytes, DEFAULT_ORDER);
}
/**
* byte数组转short<br>
* 自定义端序
*
* @param bytes byte数组
* @param bytes byte数组长度必须为2
* @param byteOrder 端序
* @return short值
*/
@@ -79,7 +87,7 @@ public class ByteUtil {
* @return byte数组
*/
public static byte[] shortToBytes(short shortValue) {
return shortToBytes(shortValue, ByteOrder.LITTLE_ENDIAN);
return shortToBytes(shortValue, DEFAULT_ORDER);
}
/**
@@ -110,7 +118,7 @@ public class ByteUtil {
* @return int值
*/
public static int bytesToInt(byte[] bytes) {
return bytesToInt(bytes, ByteOrder.LITTLE_ENDIAN);
return bytesToInt(bytes, DEFAULT_ORDER);
}
/**
@@ -144,7 +152,7 @@ public class ByteUtil {
* @return byte数组
*/
public static byte[] intToBytes(int intValue) {
return intToBytes(intValue, ByteOrder.LITTLE_ENDIAN);
return intToBytes(intValue, DEFAULT_ORDER);
}
/**
@@ -185,7 +193,7 @@ public class ByteUtil {
* @return byte数组
*/
public static byte[] longToBytes(long longValue) {
return longToBytes(longValue, ByteOrder.LITTLE_ENDIAN);
return longToBytes(longValue, DEFAULT_ORDER);
}
/**
@@ -222,7 +230,7 @@ public class ByteUtil {
* @return long值
*/
public static long bytesToLong(byte[] bytes) {
return bytesToLong(bytes, ByteOrder.LITTLE_ENDIAN);
return bytesToLong(bytes, DEFAULT_ORDER);
}
/**
@@ -251,6 +259,54 @@ public class ByteUtil {
return values;
}
/**
* float转byte数组默认以小端序转换<br>
*
* @param floatValue float值
* @return byte数组
* @since 5.7.18
*/
public static byte[] floatToBytes(float floatValue) {
return floatToBytes(floatValue, DEFAULT_ORDER);
}
/**
* float转byte数组自定义端序<br>
*
* @param floatValue float值
* @param byteOrder 端序
* @return byte数组
* @since 5.7.18
*/
public static byte[] floatToBytes(float floatValue, ByteOrder byteOrder) {
return intToBytes(Float.floatToIntBits(floatValue), byteOrder);
}
/**
* byte数组转float<br>
* 默认以小端序转换<br>
*
* @param bytes byte数组
* @return float值
* @since 5.7.18
*/
public static double bytesToFloat(byte[] bytes) {
return bytesToFloat(bytes, DEFAULT_ORDER);
}
/**
* byte数组转float<br>
* 自定义端序<br>
*
* @param bytes byte数组
* @param byteOrder 端序
* @return float值
* @since 5.7.18
*/
public static float bytesToFloat(byte[] bytes, ByteOrder byteOrder) {
return Float.intBitsToFloat(bytesToInt(bytes, byteOrder));
}
/**
* double转byte数组<br>
* 默认以小端序转换<br>
@@ -259,7 +315,7 @@ public class ByteUtil {
* @return byte数组
*/
public static byte[] doubleToBytes(double doubleValue) {
return doubleToBytes(doubleValue, ByteOrder.LITTLE_ENDIAN);
return doubleToBytes(doubleValue, DEFAULT_ORDER);
}
/**
@@ -283,7 +339,7 @@ public class ByteUtil {
* @return long值
*/
public static double bytesToDouble(byte[] bytes) {
return bytesToDouble(bytes, ByteOrder.LITTLE_ENDIAN);
return bytesToDouble(bytes, DEFAULT_ORDER);
}
/**
@@ -305,7 +361,7 @@ public class ByteUtil {
* @return bytes
*/
public static byte[] numberToBytes(Number number) {
return numberToBytes(number, ByteOrder.LITTLE_ENDIAN);
return numberToBytes(number, DEFAULT_ORDER);
}
/**
@@ -324,8 +380,62 @@ public class ByteUtil {
return intToBytes((Integer) number, byteOrder);
} else if (number instanceof Short) {
return shortToBytes((Short) number, byteOrder);
} else if (number instanceof Float) {
return floatToBytes((Float) number, byteOrder);
} else {
return doubleToBytes(number.doubleValue(), byteOrder);
}
}
/**
* byte数组转换为指定类型数字
*
* @param <T> 数字类型
* @param bytes byte数组
* @param targetClass 目标数字类型
* @param byteOrder 端序
* @return 转换后的数字
* @throws IllegalArgumentException 不支持的数字类型,如用户自定义数字类型
*/
@SuppressWarnings("unchecked")
public static <T extends Number> T bytesToNumber(byte[] bytes, Class<T> targetClass, ByteOrder byteOrder) throws IllegalArgumentException {
Number number;
if (Byte.class == targetClass) {
number = bytes[0];
} else if (Short.class == targetClass) {
number = bytesToShort(bytes, byteOrder);
} else if (Integer.class == targetClass) {
number = bytesToInt(bytes, byteOrder);
} else if (AtomicInteger.class == targetClass) {
number = new AtomicInteger(bytesToInt(bytes, byteOrder));
} else if (Long.class == targetClass) {
number = bytesToLong(bytes, byteOrder);
} else if (AtomicLong.class == targetClass) {
number = new AtomicLong(bytesToLong(bytes, byteOrder));
} else if (LongAdder.class == targetClass) {
final LongAdder longValue = new LongAdder();
longValue.add(bytesToLong(bytes, byteOrder));
number = longValue;
} else if (Float.class == targetClass) {
number = bytesToFloat(bytes, byteOrder);
} else if (Double.class == targetClass) {
number = bytesToDouble(bytes, byteOrder);
} else if (DoubleAdder.class == targetClass) {
final DoubleAdder doubleAdder = new DoubleAdder();
doubleAdder.add(bytesToDouble(bytes, byteOrder));
number = doubleAdder;
} else if (BigDecimal.class == targetClass) {
number = NumberUtil.toBigDecimal(bytesToDouble(bytes, byteOrder));
} else if (BigInteger.class == targetClass) {
number = BigInteger.valueOf(bytesToLong(bytes, byteOrder));
} else if (Number.class == targetClass) {
// 用户没有明确类型具体类型默认Double
number = bytesToDouble(bytes, byteOrder);
} else {
// 用户自定义类型不支持
throw new IllegalArgumentException("Unsupported Number type: " + targetClass.getName());
}
return (T) number;
}
}

View File

@@ -6,6 +6,7 @@ import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ByteUtil;
import cn.hutool.core.util.HexUtil;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
@@ -343,4 +344,13 @@ public class ConvertTest {
final BigDecimal bigDecimal = Convert.toBigDecimal(str);
Assert.assertEquals(str, bigDecimal.toPlainString());
}
@Test
public void toFloatTest(){
// https://gitee.com/dromara/hutool/issues/I4M0E4
String hex2 = "CD0CCB43";
final byte[] value = HexUtil.decodeHex(hex2);
final float f = Convert.toFloat(value);
Assert.assertEquals(406.1F, f, 2);
}
}

View File

@@ -10,7 +10,7 @@ public class ByteUtilTest {
@Test
public void intAndBytesLittleEndianTest() {
// 测试 int 转小端序 byte 数组
int int1 = 1417;
int int1 = RandomUtil.randomInt();
byte[] bytesInt = ByteUtil.intToBytes(int1, ByteOrder.LITTLE_ENDIAN);
int int2 = ByteUtil.bytesToInt(bytesInt, ByteOrder.LITTLE_ENDIAN);
@@ -28,7 +28,7 @@ public class ByteUtilTest {
@Test
public void intAndBytesBigEndianTest() {
// 测试 int 转大端序 byte 数组
int int2 = 1417;
int int2 = RandomUtil.randomInt();
byte[] bytesInt = ByteUtil.intToBytes(int2, ByteOrder.BIG_ENDIAN);
// 测试大端序 byte 数组转 int
@@ -65,9 +65,30 @@ public class ByteUtilTest {
Assert.assertEquals(long1, long2);
}
@Test
public void floatAndBytesLittleEndianTest() {
// 测试 long 转 byte 数组
float f1 = (float) RandomUtil.randomDouble();
byte[] bytesLong = ByteUtil.floatToBytes(f1, ByteOrder.LITTLE_ENDIAN);
float f2 = ByteUtil.bytesToFloat(bytesLong, ByteOrder.LITTLE_ENDIAN);
Assert.assertEquals(f1, f2, 2);
}
@Test
public void floatAndBytesBigEndianTest() {
// 测试大端序 long 转 byte 数组
float f1 = (float) RandomUtil.randomDouble();
byte[] bytesLong = ByteUtil.floatToBytes(f1, ByteOrder.BIG_ENDIAN);
float f2 = ByteUtil.bytesToFloat(bytesLong, ByteOrder.BIG_ENDIAN);
Assert.assertEquals(f1, f2, 2);
}
@Test
public void shortAndBytesLittleEndianTest() {
short short1 = 122;
short short1 = (short) RandomUtil.randomInt();
byte[] bytes = ByteUtil.shortToBytes(short1, ByteOrder.LITTLE_ENDIAN);
short short2 = ByteUtil.bytesToShort(bytes, ByteOrder.LITTLE_ENDIAN);