diff --git a/CHANGELOG.md b/CHANGELOG.md index 30aa85d8b..58a5de0e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,9 +3,11 @@ ------------------------------------------------------------------------------------------------------------- -# 5.6.3 (2021-03-28) +# 5.6.3 (2021-03-31) ### 新特性 +* 【core 】 修改数字转换的实现,增加按照指定端序转换(pr#1492@Github) +* 【core 】 修改拆分byte数组时最后一组长度的规则(pr#1494@Github) ### Bug修复 ------------------------------------------------------------------------------------------------------------- diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/Convert.java b/hutool-core/src/main/java/cn/hutool/core/convert/Convert.java index b3a45362c..50a2602c7 100644 --- a/hutool-core/src/main/java/cn/hutool/core/convert/Convert.java +++ b/hutool-core/src/main/java/cn/hutool/core/convert/Convert.java @@ -6,6 +6,7 @@ import cn.hutool.core.convert.impl.MapConverter; import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.TypeReference; import cn.hutool.core.text.UnicodeUtil; +import cn.hutool.core.util.ByteUtil; import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.util.ClassUtil; import cn.hutool.core.util.HexUtil; @@ -1044,92 +1045,76 @@ public class Convert { } /** - * byte数组转short + * byte数组转short
+ * 默认以小端序转换 * * @param bytes byte数组 * @return short值 - * @since 3.2.0 + * @since 5.6.3 */ public static short bytesToShort(byte[] bytes) { - return (short) (bytes[1] & 0xff | (bytes[0] & 0xff) << 8); + return ByteUtil.bytesToShort(bytes); } /** - * short转byte数组 + * short转byte数组
+ * 默认以小端序转换 + * * @param shortValue short值 * @return byte数组 - * @since 3.2.0 + * @since 5.6.3 */ public static byte[] shortToBytes(short shortValue) { - byte[] b = new byte[2]; - b[1] = (byte) (shortValue & 0xff); - b[0] = (byte) ((shortValue >> 8) & 0xff); - return b; + return ByteUtil.shortToBytes(shortValue); } /** - * byte[]转int值 + * byte[]转int值
+ * 默认以小端序转换 * * @param bytes byte数组 * @return int值 - * @since 3.2.0 + * @since 5.6.3 */ public static int bytesToInt(byte[] bytes) { - return bytes[3] & 0xFF | // - (bytes[2] & 0xFF) << 8 | // - (bytes[1] & 0xFF) << 16 | // - (bytes[0] & 0xFF) << 24; // + return ByteUtil.bytesToInt(bytes); } /** - * int转byte数组 + * int转byte数组
+ * 默认以小端序转换 * * @param intValue int值 * @return byte数组 - * @since 3.2.0 + * @since 5.6.3 */ public static byte[] intToBytes(int intValue) { - return new byte[] { // - (byte) ((intValue >> 24) & 0xFF), // - (byte) ((intValue >> 16) & 0xFF), // - (byte) ((intValue >> 8) & 0xFF), // - (byte) (intValue & 0xFF) // - }; + return ByteUtil.intToBytes(intValue); } /** * long转byte数组
+ * 默认以小端序转换
* from: https://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java * * @param longValue long值 * @return byte数组 - * @since 3.2.0 + * @since 5.6.3 */ public static byte[] longToBytes(long longValue) { - // Magic number 8 should be defined as Long.SIZE / Byte.SIZE - final byte[] result = new byte[8]; - for (int i = 7; i >= 0; i--) { - result[i] = (byte) (longValue & 0xFF); - longValue >>= 8; - } - return result; + return ByteUtil.longToBytes(longValue); } /** * byte数组转long
+ * 默认以小端序转换
* from: https://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java * * @param bytes byte数组 * @return long值 - * @since 3.2.0 + * @since 5.6.3 */ public static long bytesToLong(byte[] bytes) { - // Magic number 8 should be defined as Long.SIZE / Byte.SIZE - long values = 0; - for (int i = 0; i < 8; i++) { - values <<= 8; - values |= (bytes[i] & 0xff); - } - return values; + return ByteUtil.bytesToLong(bytes); } } diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/ConverterRegistry.java b/hutool-core/src/main/java/cn/hutool/core/convert/ConverterRegistry.java index 40fb260f8..6800a9213 100644 --- a/hutool-core/src/main/java/cn/hutool/core/convert/ConverterRegistry.java +++ b/hutool-core/src/main/java/cn/hutool/core/convert/ConverterRegistry.java @@ -298,7 +298,7 @@ public class ConverterRegistry implements Serializable { * @param 转换的目标类型(转换器转换到的类型) * @param type 类型 * @param value 值 - * @return 转换后的值,默认为null + * @return 转换后的值,默认为{@code null} * @throws ConvertException 转换器不存在 */ public T convert(Type type, Object value) throws ConvertException { diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/impl/ArrayConverter.java b/hutool-core/src/main/java/cn/hutool/core/convert/impl/ArrayConverter.java index e3fddf479..b0793d50c 100644 --- a/hutool-core/src/main/java/cn/hutool/core/convert/impl/ArrayConverter.java +++ b/hutool-core/src/main/java/cn/hutool/core/convert/impl/ArrayConverter.java @@ -4,6 +4,7 @@ import cn.hutool.core.collection.IterUtil; import cn.hutool.core.convert.AbstractConverter; import cn.hutool.core.convert.Convert; import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.ByteUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; @@ -159,6 +160,9 @@ public class ArrayConverter extends AbstractConverter { for (int i = 0; i < list.size(); i++) { Array.set(result, i, convertComponentType(list.get(i))); } + }else if (value instanceof Number && byte.class == targetComponentType) { + // 用户可能想序列化指定对象 + result = ByteUtil.numberToBytes((Number)value); } else if (value instanceof Serializable && byte.class == targetComponentType) { // 用户可能想序列化指定对象 result = ObjectUtil.serialize(value); diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/impl/NumberConverter.java b/hutool-core/src/main/java/cn/hutool/core/convert/impl/NumberConverter.java index a5e547b8c..25d05fe8c 100644 --- a/hutool-core/src/main/java/cn/hutool/core/convert/impl/NumberConverter.java +++ b/hutool-core/src/main/java/cn/hutool/core/convert/impl/NumberConverter.java @@ -3,6 +3,7 @@ package cn.hutool.core.convert.impl; import cn.hutool.core.convert.AbstractConverter; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.BooleanUtil; +import cn.hutool.core.util.ByteUtil; import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.StrUtil; @@ -90,6 +91,8 @@ public class NumberConverter extends AbstractConverter { 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{ @@ -108,6 +111,8 @@ public class NumberConverter extends AbstractConverter { 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); @@ -129,6 +134,8 @@ public class NumberConverter extends AbstractConverter { 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); @@ -152,6 +159,8 @@ public class NumberConverter extends AbstractConverter { 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); @@ -160,6 +169,8 @@ public class NumberConverter extends AbstractConverter { 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); @@ -202,6 +213,8 @@ public class NumberConverter extends AbstractConverter { 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)); } //对于Double类型,先要转换为String,避免精度问题 @@ -222,6 +235,8 @@ public class NumberConverter extends AbstractConverter { 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 NumberUtil.toBigInteger(toStrFunc.apply(value)); diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/impl/PrimitiveConverter.java b/hutool-core/src/main/java/cn/hutool/core/convert/impl/PrimitiveConverter.java index 53712fd17..36b092b09 100644 --- a/hutool-core/src/main/java/cn/hutool/core/convert/impl/PrimitiveConverter.java +++ b/hutool-core/src/main/java/cn/hutool/core/convert/impl/PrimitiveConverter.java @@ -12,14 +12,14 @@ import java.util.function.Function; * 原始类型转换器
* 支持类型为:
*
    - *
  • byte
  • - *
  • short
  • - *
  • int
  • - *
  • long
  • - *
  • float
  • - *
  • double
  • - *
  • char
  • - *
  • boolean
  • + *
  • {@code byte}
  • + *
  • {@code short}
  • + *
  • {@code int}
  • + *
  • {@code long}
  • + *
  • {@code float}
  • + *
  • {@code double}
  • + *
  • {@code char}
  • + *
  • {@code boolean}
  • *
* * @author Looly diff --git a/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java index 530f28a05..3aae4956c 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java @@ -1365,7 +1365,8 @@ public class ArrayUtil extends PrimitiveArrayUtil { * @return 变更后的原数组 * @since 3.0.9 */ - public static T[] reverse(T[] array, final int startIndexInclusive, final int endIndexExclusive) { + public static T[] + reverse(T[] array, final int startIndexInclusive, final int endIndexExclusive) { if (isEmpty(array)) { return array; } diff --git a/hutool-core/src/main/java/cn/hutool/core/util/ByteUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/ByteUtil.java new file mode 100644 index 000000000..78ee8b4f6 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/util/ByteUtil.java @@ -0,0 +1,330 @@ +package cn.hutool.core.util; + +import java.nio.ByteOrder; + +/** + * 对数字和字节进行转换。
+ * 假设数据存储是以大端模式存储的:
+ *
    + *
  • byte: 字节类型 占8位二进制 00000000
  • + *
  • char: 字符类型 占2个字节 16位二进制 byte[0] byte[1]
  • + *
  • int : 整数类型 占4个字节 32位二进制 byte[0] byte[1] byte[2] byte[3]
  • + *
  • long: 长整数类型 占8个字节 64位二进制 byte[0] byte[1] byte[2] byte[3] byte[4] byte[5]
  • + *
  • long: 长整数类型 占8个字节 64位二进制 byte[0] byte[1] byte[2] byte[3] byte[4] byte[5] byte[6] byte[7]
  • + *
  • float: 浮点数(小数) 占4个字节 32位二进制 byte[0] byte[1] byte[2] byte[3]
  • + *
  • double: 双精度浮点数(小数) 占8个字节 64位二进制 byte[0] byte[1] byte[2] byte[3] byte[4]byte[5] byte[6] byte[7]
  • + *
+ * 注:注释来自Hanlp,代码提供来自pr#1492@Github + * + * @author looly, hanlp, FULaBUla + * @since 5.6.3 + */ +public class ByteUtil { + + /** + * int转byte + * + * @param intValue int值 + * @return byte值 + */ + public static byte intToByte(int intValue) { + return (byte) intValue; + } + + /** + * byte转无符号int + * + * @param byteValue byte值 + * @return 无符号int值 + * @since 3.2.0 + */ + public static int byteToUnsignedInt(byte byteValue) { + // Java 总是把 byte 当做有符处理;我们可以通过将其和 0xFF 进行二进制与得到它的无符值 + return byteValue & 0xFF; + } + + /** + * byte数组转short
+ * 默认以小端序转换 + * + * @param bytes byte数组 + * @return short值 + */ + public static short bytesToShort(byte[] bytes) { + return bytesToShort(bytes, ByteOrder.LITTLE_ENDIAN); + } + + /** + * byte数组转short
+ * 自定义端序 + * + * @param bytes byte数组 + * @param byteOrder 端序 + * @return short值 + */ + public static short bytesToShort(byte[] bytes, ByteOrder byteOrder) { + if (ByteOrder.LITTLE_ENDIAN == byteOrder) { + return (short) (bytes[1] & 0xff | (bytes[0] & 0xff) << Byte.SIZE); + } else { + return (short) (bytes[0] & 0xff | (bytes[1] & 0xff) << Byte.SIZE); + } + } + + /** + * short转byte数组
+ * 默认以小端序转换 + * + * @param shortValue short值 + * @return byte数组 + */ + public static byte[] shortToBytes(short shortValue) { + return shortToBytes(shortValue, ByteOrder.LITTLE_ENDIAN); + } + + /** + * short转byte数组
+ * 自定义端序 + * + * @param shortValue short值 + * @param byteOrder 端序 + * @return byte数组 + */ + public static byte[] shortToBytes(short shortValue, ByteOrder byteOrder) { + byte[] b = new byte[Short.BYTES]; + if (ByteOrder.LITTLE_ENDIAN == byteOrder) { + b[1] = (byte) (shortValue & 0xff); + b[0] = (byte) ((shortValue >> Byte.SIZE) & 0xff); + } else { + b[0] = (byte) (shortValue & 0xff); + b[1] = (byte) ((shortValue >> Byte.SIZE) & 0xff); + } + return b; + } + + /** + * byte[]转int值
+ * 默认以小端序转换 + * + * @param bytes byte数组 + * @return int值 + */ + public static int bytesToInt(byte[] bytes) { + return bytesToInt(bytes, ByteOrder.LITTLE_ENDIAN); + } + + /** + * byte[]转int值
+ * 自定义端序 + * + * @param bytes byte数组 + * @param byteOrder 端序 + * @return int值 + */ + public static int bytesToInt(byte[] bytes, ByteOrder byteOrder) { + if (ByteOrder.LITTLE_ENDIAN == byteOrder) { + return bytes[3] & 0xFF | // + (bytes[2] & 0xFF) << 8 | // + (bytes[1] & 0xFF) << 16 | // + (bytes[0] & 0xFF) << 24; // + } else { + return bytes[0] & 0xFF | // + (bytes[1] & 0xFF) << 8 | // + (bytes[2] & 0xFF) << 16 | // + (bytes[3] & 0xFF) << 24; // + } + + } + + /** + * int转byte数组
+ * 默认以小端序转换 + * + * @param intValue int值 + * @return byte数组 + */ + public static byte[] intToBytes(int intValue) { + return intToBytes(intValue, ByteOrder.LITTLE_ENDIAN); + } + + /** + * int转byte数组
+ * 自定义端序 + * + * @param intValue int值 + * @param byteOrder 端序 + * @return byte数组 + */ + public static byte[] intToBytes(int intValue, ByteOrder byteOrder) { + + if (ByteOrder.LITTLE_ENDIAN == byteOrder) { + return new byte[]{ // + (byte) ((intValue >> 24) & 0xFF), // + (byte) ((intValue >> 16) & 0xFF), // + (byte) ((intValue >> 8) & 0xFF), // + (byte) (intValue & 0xFF) // + }; + + } else { + return new byte[]{ // + (byte) (intValue & 0xFF), // + (byte) ((intValue >> 8) & 0xFF), // + (byte) ((intValue >> 16) & 0xFF), // + (byte) ((intValue >> 24) & 0xFF) // + }; + } + + + } + + /** + * long转byte数组
+ * 默认以小端序转换
+ * from: https://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java + * + * @param longValue long值 + * @return byte数组 + */ + public static byte[] longToBytes(long longValue) { + return longToBytes(longValue, ByteOrder.LITTLE_ENDIAN); + } + + /** + * long转byte数组
+ * 自定义端序
+ * from: https://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java + * + * @param longValue long值 + * @param byteOrder 端序 + * @return byte数组 + */ + public static byte[] longToBytes(long longValue, ByteOrder byteOrder) { + byte[] result = new byte[Long.BYTES]; + if (ByteOrder.LITTLE_ENDIAN == byteOrder) { + for (int i = (result.length - 1); i >= 0; i--) { + result[i] = (byte) (longValue & 0xFF); + longValue >>= Byte.SIZE; + } + } else { + for (int i = 0; i < result.length; i++) { + result[i] = (byte) (longValue & 0xFF); + longValue >>= Byte.SIZE; + } + } + + return result; + } + + /** + * byte数组转long
+ * 默认以小端序转换
+ * from: https://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java + * + * @param bytes byte数组 + * @return long值 + */ + public static long bytesToLong(byte[] bytes) { + return bytesToLong(bytes, ByteOrder.LITTLE_ENDIAN); + } + + /** + * byte数组转long
+ * 自定义端序
+ * from: https://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java + * + * @param bytes byte数组 + * @param byteOrder 端序 + * @return long值 + */ + public static long bytesToLong(byte[] bytes, ByteOrder byteOrder) { + long values = 0; + if (ByteOrder.LITTLE_ENDIAN == byteOrder) { + for (int i = 0; i < Long.BYTES; i++) { + values <<= Byte.SIZE; + values |= (bytes[i] & 0xff); + } + } else { + for (int i = (Long.BYTES - 1); i >= 0; i--) { + values <<= Byte.SIZE; + values |= (bytes[i] & 0xff); + } + } + + return values; + } + + /** + * double转byte数组
+ * 默认以小端序转换
+ * + * @param doubleValue double值 + * @return byte数组 + */ + public static byte[] doubleToBytes(double doubleValue) { + return doubleToBytes(doubleValue, ByteOrder.LITTLE_ENDIAN); + } + + /** + * double转byte数组
+ * 自定义端序
+ * from: https://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java + * + * @param doubleValue double值 + * @param byteOrder 端序 + * @return byte数组 + */ + public static byte[] doubleToBytes(double doubleValue, ByteOrder byteOrder) { + return longToBytes(Double.doubleToLongBits(doubleValue), byteOrder); + } + + /** + * byte数组转Double
+ * 默认以小端序转换
+ * + * @param bytes byte数组 + * @return long值 + */ + public static double bytesToDouble(byte[] bytes) { + return bytesToDouble(bytes, ByteOrder.LITTLE_ENDIAN); + } + + /** + * byte数组转double
+ * 自定义端序
+ * + * @param bytes byte数组 + * @param byteOrder 端序 + * @return long值 + */ + public static double bytesToDouble(byte[] bytes, ByteOrder byteOrder) { + return Double.longBitsToDouble(bytesToLong(bytes, byteOrder)); + } + + /** + * 将{@link Number}转换为 + * @param number 数字 + * @return bytes + */ + public static byte[] numberToBytes(Number number){ + return numberToBytes(number, ByteOrder.LITTLE_ENDIAN); + } + + /** + * 将{@link Number}转换为 + * @param number 数字 + * @param byteOrder 端序 + * @return bytes + */ + public static byte[] numberToBytes(Number number, ByteOrder byteOrder){ + if(number instanceof Double){ + return doubleToBytes((Double) number, byteOrder); + } else if(number instanceof Long){ + return longToBytes((Long) number, byteOrder); + } else if(number instanceof Integer){ + return intToBytes((Integer) number, byteOrder); + } else if(number instanceof Short){ + return shortToBytes((Short) number, byteOrder); + } else{ + return doubleToBytes(number.doubleValue(), byteOrder); + } + } +} diff --git a/hutool-core/src/main/java/cn/hutool/core/util/CharUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/CharUtil.java index ee2650136..820b3e736 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/CharUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/CharUtil.java @@ -375,26 +375,9 @@ public class CharUtil { * 'a' -》 'ⓐ' * * - * 获取带圈数字 /封闭式字母数字 ,从1-20,超过1-20报错 - * 0 1 2 3 4 5 6 7 8 9 A B C D E F - * U+246x ① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩ ⑪ ⑫ ⑬ ⑭ ⑮ ⑯ - * U+247x ⑰ ⑱ ⑲ ⑳ ⑴ ⑵ ⑶ ⑷ ⑸ ⑹ ⑺ ⑻ ⑼ ⑽ ⑾ ⑿ - * U+248x ⒀ ⒁ ⒂ ⒃ ⒄ ⒅ ⒆ ⒇ ⒈ ⒉ ⒊ ⒋ ⒌ ⒍ ⒎ ⒏ - * U+249x ⒐ ⒑ ⒒ ⒓ ⒔ ⒕ ⒖ ⒗ ⒘ ⒙ ⒚ ⒛ ⒜ ⒝ ⒞ ⒟ - * U+24Ax ⒠ ⒡ ⒢ ⒣ ⒤ ⒥ ⒦ ⒧ ⒨ ⒩ ⒪ ⒫ ⒬ ⒭ ⒮ ⒯ - * U+24Bx ⒰ ⒱ ⒲ ⒳ ⒴ ⒵ Ⓐ Ⓑ Ⓒ Ⓓ Ⓔ Ⓕ Ⓖ Ⓗ Ⓘ Ⓙ - * U+24Cx Ⓚ Ⓛ Ⓜ Ⓝ Ⓞ Ⓟ Ⓠ Ⓡ Ⓢ Ⓣ Ⓤ Ⓥ Ⓦ Ⓧ Ⓨ Ⓩ - * U+24Dx ⓐ ⓑ ⓒ ⓓ ⓔ ⓕ ⓖ ⓗ ⓘ ⓙ ⓚ ⓛ ⓜ ⓝ ⓞ ⓟ - * U+24Ex ⓠ ⓡ ⓢ ⓣ ⓤ ⓥ ⓦ ⓧ ⓨ ⓩ ⓪ ⓫ ⓬ ⓭ ⓮ ⓯ - * U+24Fx ⓰ ⓱ ⓲ ⓳ ⓴ ⓵ ⓶ ⓷ ⓸ ⓹ ⓺ ⓻ ⓼ ⓽ ⓾ ⓿ - * @link Unicode_symbols https://en.wikipedia.org/wiki/List_of_Unicode_characters#Unicode_symbols - * @link Enclosed Alphanumerics https://en.wikipedia.org/wiki/Enclosed_Alphanumerics - * 有其他特殊的需求,可以到 维基百科 查找说明 - * * @param c 被转换的字符,如果字符不支持转换,返回原字符 * @return 转换后的字符 * @since 5.6.2 - * @author dazer */ public static char toCloseChar(char c){ int result = c; @@ -416,15 +399,14 @@ public class CharUtil { * 20 -》 '⑳' * * 也称作:封闭式字符,英文:Enclosed Alphanumerics - * @author dazer + * 见: 维基百科wikipedia-Unicode_symbols https://en.wikipedia.org/wiki/List_of_Unicode_characters#Unicode_symbols + * 见: 维基百科wikipedia-Unicode字符列表 https://zh.wikipedia.org/wiki/Unicode%E5%AD%97%E7%AC%A6%E5%88%97%E8%A1%A8 + * 见: coolsymbol https://coolsymbol.com/ + * 见: 百度百科 https://baike.baidu.com/item/%E7%89%B9%E6%AE%8A%E5%AD%97%E7%AC%A6/112715?fr=aladdin + * * @param number 被转换的数字 * @return 转换后的字符 * @since 5.6.2 - * - * @link 维基百科wikipedia-Unicode_symbols https://en.wikipedia.org/wiki/List_of_Unicode_characters#Unicode_symbols - * @link 维基百科wikipedia-Unicode字符列表 https://zh.wikipedia.org/wiki/Unicode%E5%AD%97%E7%AC%A6%E5%88%97%E8%A1%A8 - * @link coolsymbol https://coolsymbol.com/ - * @link 百度百科 https://baike.baidu.com/item/%E7%89%B9%E6%AE%8A%E5%AD%97%E7%AC%A6/112715?fr=aladdin */ public static char toCloseByNumber(int number){ if(number > 20){ @@ -432,14 +414,4 @@ public class CharUtil { } return (char) ('①' + number - 1); } - - /** - * 获取带圈字符 - * Enclosed Alphanumerics - * @since 5.6.3 - * @see CharUtil#toEnclosedAlphanumericsCircleByInt(int) - */ - public static char toEnclosedAlphanumericsCircleByInt(int number){ - return CharUtil.toCloseByNumber(number); - } } diff --git a/hutool-core/src/main/java/cn/hutool/core/util/PrimitiveArrayUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/PrimitiveArrayUtil.java index f0e1a2ee9..f554679ac 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/PrimitiveArrayUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/PrimitiveArrayUtil.java @@ -520,26 +520,27 @@ public class PrimitiveArrayUtil { // ---------------------------------------------------------------------- split /** - * 拆分byte数组为几个等份(最后一份可能小于len) + * 拆分byte数组为几个等份(最后一份按照剩余长度分配空间) * * @param array 数组 * @param len 每个小节的长度 * @return 拆分后的数组 */ public static byte[][] split(byte[] array, int len) { - int x = array.length / len; - int y = array.length % len; - int z = 0; - if (y != 0) { - z = 1; + int amount = array.length / len; + final int remainder = array.length % len; + if (remainder != 0) { + ++amount; } - byte[][] arrays = new byte[x + z][]; + final byte[][] arrays = new byte[amount][]; byte[] arr; - for (int i = 0; i < x + z; i++) { - arr = new byte[len]; - if (i == x + z - 1 && y != 0) { - System.arraycopy(array, i * len, arr, 0, y); + for (int i = 0; i < amount; i++) { + if (i == amount - 1 && remainder != 0) { + // 有剩余,按照实际长度创建 + arr = new byte[remainder]; + System.arraycopy(array, i * len, arr, 0, remainder); } else { + arr = new byte[len]; System.arraycopy(array, i * len, arr, 0, len); } arrays[i] = arr; diff --git a/hutool-core/src/test/java/cn/hutool/core/annotation/AnnotationUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/annotation/AnnotationUtilTest.java index 3980c433d..b565cbcb6 100644 --- a/hutool-core/src/test/java/cn/hutool/core/annotation/AnnotationUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/annotation/AnnotationUtilTest.java @@ -4,15 +4,18 @@ import org.junit.Assert; import org.junit.Test; public class AnnotationUtilTest { - + @Test public void getAnnotationValueTest() { Object value = AnnotationUtil.getAnnotationValue(ClassWithAnnotation.class, AnnotationForTest.class); Assert.assertEquals("测试", value); + } - + @AnnotationForTest("测试") static class ClassWithAnnotation{ - + public void test(){ + + } } } diff --git a/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java index 51626279f..209e4dba5 100644 --- a/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java @@ -577,6 +577,7 @@ public class BeanUtilTest { private String name; private TestPojo2[] testPojo2List; } + @Data public static class TestPojo2{ private int age; diff --git a/hutool-core/src/test/java/cn/hutool/core/convert/ConvertTest.java b/hutool-core/src/test/java/cn/hutool/core/convert/ConvertTest.java index 9b1f042a0..0157610e2 100644 --- a/hutool-core/src/test/java/cn/hutool/core/convert/ConvertTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/convert/ConvertTest.java @@ -3,6 +3,7 @@ package cn.hutool.core.convert; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateException; import cn.hutool.core.lang.TypeReference; +import cn.hutool.core.util.ByteUtil; import lombok.AllArgsConstructor; import lombok.Data; import lombok.Getter; @@ -194,8 +195,8 @@ public class ConvertTest { } @Test - public void toListTest(){ - List list = Arrays.asList("1","2"); + public void toListTest() { + List list = Arrays.asList("1", "2"); String str = Convert.toStr(list); List list2 = Convert.toList(String.class, str); Assert.assertEquals("1", list2.get(0)); @@ -230,6 +231,13 @@ public class ConvertTest { Assert.assertEquals("5.1.1", product.getVersion()); } + @Test + public void numberToByteArrayTest(){ + // 测试Serializable转换为bytes,调用序列化转换 + final byte[] bytes = Convert.toPrimitiveByteArray(12L); + Assert.assertArrayEquals(ByteUtil.longToBytes(12L), bytes); + } + @Test public void toAtomicIntegerArrayTest(){ String str = "1,2"; diff --git a/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java index ac3f6c719..5df5ad6c6 100644 --- a/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java @@ -424,4 +424,12 @@ public class ArrayUtilTest { Assert.assertTrue(o instanceof Integer); } } + + @Test + public void splitTest() { + byte[] array = new byte[1024]; + byte[][] arrayAfterSplit = ArrayUtil.split(array, 500); + Assert.assertEquals(3, arrayAfterSplit.length); + Assert.assertEquals(24, arrayAfterSplit[2].length); + } } diff --git a/hutool-core/src/test/java/cn/hutool/core/util/ByteUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/ByteUtilTest.java new file mode 100644 index 000000000..a8bd49721 --- /dev/null +++ b/hutool-core/src/test/java/cn/hutool/core/util/ByteUtilTest.java @@ -0,0 +1,92 @@ +package cn.hutool.core.util; + +import org.junit.Assert; +import org.junit.Test; + +import java.nio.ByteOrder; + +public class ByteUtilTest { + @Test + public void intAndBytesLittleEndianTest() { + // 测试 int 转小端序 byte 数组 + int int1 = 1417; + + byte[] bytesInt = ByteUtil.intToBytes(int1, ByteOrder.LITTLE_ENDIAN); + int int2 = ByteUtil.bytesToInt(bytesInt, ByteOrder.LITTLE_ENDIAN); + Assert.assertEquals(int1, int2); + + byte[] bytesInt2 = ByteUtil.intToBytes(int1, ByteOrder.LITTLE_ENDIAN); + int int3 = ByteUtil.bytesToInt(bytesInt2, ByteOrder.LITTLE_ENDIAN); + Assert.assertEquals(int1, int3); + + byte[] bytesInt3 = ByteUtil.intToBytes(int1, ByteOrder.LITTLE_ENDIAN); + int int4 = ByteUtil.bytesToInt(bytesInt3, ByteOrder.LITTLE_ENDIAN); + Assert.assertEquals(int1, int4); + } + + @Test + public void intAndBytesBigEndianTest() { + // 测试 int 转大端序 byte 数组 + int int2 = 1417; + byte[] bytesInt = ByteUtil.intToBytes(int2, ByteOrder.BIG_ENDIAN); + + // 测试大端序 byte 数组转 int + int int3 = ByteUtil.bytesToInt(bytesInt, ByteOrder.BIG_ENDIAN); + Assert.assertEquals(int2, int3); + } + + @Test + public void longAndBytesLittleEndianTest() { + // 测试 long 转 byte 数组 + long long1 = 2223; + + byte[] bytesLong = ByteUtil.longToBytes(long1, ByteOrder.LITTLE_ENDIAN); + long long2 = ByteUtil.bytesToLong(bytesLong, ByteOrder.LITTLE_ENDIAN); + Assert.assertEquals(long1, long2); + + byte[] bytesLong2 = ByteUtil.longToBytes(long1); + long long3 = ByteUtil.bytesToLong(bytesLong2, ByteOrder.LITTLE_ENDIAN); + Assert.assertEquals(long1, long3); + + byte[] bytesLong3 = ByteUtil.longToBytes(long1, ByteOrder.LITTLE_ENDIAN); + long long4 = ByteUtil.bytesToLong(bytesLong3); + Assert.assertEquals(long1, long4); + } + + @Test + public void longAndBytesBigEndianTest() { + // 测试大端序 long 转 byte 数组 + long long1 = 2223; + + byte[] bytesLong = ByteUtil.longToBytes(long1, ByteOrder.BIG_ENDIAN); + long long2 = ByteUtil.bytesToLong(bytesLong, ByteOrder.BIG_ENDIAN); + + Assert.assertEquals(long1, long2); + } + + @Test + public void shortAndBytesLittleEndianTest() { + short short1 = 122; + + byte[] bytes = ByteUtil.shortToBytes(short1, ByteOrder.LITTLE_ENDIAN); + short short2 = ByteUtil.bytesToShort(bytes, ByteOrder.LITTLE_ENDIAN); + Assert.assertEquals(short2, short1); + + byte[] bytes2 = ByteUtil.shortToBytes(short1); + short short3 = ByteUtil.bytesToShort(bytes2, ByteOrder.LITTLE_ENDIAN); + Assert.assertEquals(short3, short1); + + byte[] bytes3 = ByteUtil.shortToBytes(short1, ByteOrder.LITTLE_ENDIAN); + short short4 = ByteUtil.bytesToShort(bytes3); + Assert.assertEquals(short4, short1); + } + + @Test + public void shortAndBytesBigEndianTest() { + short short1 = 122; + byte[] bytes = ByteUtil.shortToBytes(short1, ByteOrder.BIG_ENDIAN); + short short2 = ByteUtil.bytesToShort(bytes, ByteOrder.BIG_ENDIAN); + + Assert.assertEquals(short2, short1); + } +} diff --git a/hutool-crypto/src/test/java/cn/hutool/crypto/test/symmetric/SymmetricTest.java b/hutool-crypto/src/test/java/cn/hutool/crypto/test/symmetric/SymmetricTest.java index fa82a6c4f..f35386865 100644 --- a/hutool-crypto/src/test/java/cn/hutool/crypto/test/symmetric/SymmetricTest.java +++ b/hutool-crypto/src/test/java/cn/hutool/crypto/test/symmetric/SymmetricTest.java @@ -13,7 +13,7 @@ import org.junit.Test; /** * 对称加密算法单元测试 - * + * * @author Looly * */ @@ -25,7 +25,7 @@ public class SymmetricTest { // 随机生成密钥 byte[] key = KeyUtil.generateKey(SymmetricAlgorithm.AES.getValue()).getEncoded(); - + // 构建 SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, key); @@ -74,7 +74,7 @@ public class SymmetricTest { String content = "test中文aaaaaaaaaaaaaaaaaaaaa"; AES aes = new AES(Mode.CTS, Padding.PKCS5Padding, "0CoJUm6Qyw8W8jud".getBytes(), "0102030405060708".getBytes()); - + // 加密 byte[] encrypt = aes.encrypt(content); // 解密 @@ -89,12 +89,12 @@ public class SymmetricTest { Assert.assertEquals(content, decryptStr); } - + @Test public void aesTest4() { String content = "4321c9a2db2e6b08987c3b903d8d11ff"; AES aes = new AES(Mode.CBC, Padding.PKCS5Padding, "0123456789ABHAEQ".getBytes(), "DYgjCEIMVrj2W9xN".getBytes()); - + // 加密为16进制表示 String encryptHex = aes.encryptHex(content); @@ -113,6 +113,20 @@ public class SymmetricTest { Assert.assertEquals(content, decryptStr); } + @Test + public void aesPkcs7PaddingTest() { + String content = RandomUtil.randomString(RandomUtil.randomInt(200)); + AES aes = new AES("CBC", "PKCS7Padding", + "0123456789ABHAEQ".getBytes(), + "DYgjCEIMVrj2W9xN".getBytes()); + + // 加密为16进制表示 + String encryptHex = aes.encryptHex(content); + // 解密 + String decryptStr = aes.decryptStr(encryptHex); + Assert.assertEquals(content, decryptStr); + } + @Test public void desTest() { String content = "test中文"; @@ -148,21 +162,21 @@ public class SymmetricTest { Assert.assertEquals(content, decryptStr); } - + @Test public void desTest3() { String content = "test中文"; - + DES des = new DES(Mode.CTS, Padding.PKCS5Padding, "0CoJUm6Qyw8W8jud".getBytes(), "01020304".getBytes()); - + byte[] encrypt = des.encrypt(content); byte[] decrypt = des.decrypt(encrypt); - + Assert.assertEquals(content, StrUtil.utf8Str(decrypt)); - + String encryptHex = des.encryptHex(content); String decryptStr = des.decryptStr(encryptHex); - + Assert.assertEquals(content, decryptStr); } @@ -173,7 +187,7 @@ public class SymmetricTest { byte[] key = SecureUtil.generateKey(SymmetricAlgorithm.DESede.getValue()).getEncoded(); DESede des = SecureUtil.desede(key); - + byte[] encrypt = des.encrypt(content); byte[] decrypt = des.decrypt(encrypt); @@ -184,31 +198,31 @@ public class SymmetricTest { Assert.assertEquals(content, decryptStr); } - + @Test public void desdeTest2() { String content = "test中文"; - + byte[] key = SecureUtil.generateKey(SymmetricAlgorithm.DESede.getValue()).getEncoded(); - + DESede des = new DESede(Mode.CBC, Padding.PKCS5Padding, key, "12345678".getBytes()); - + byte[] encrypt = des.encrypt(content); byte[] decrypt = des.decrypt(encrypt); - + Assert.assertEquals(content, StrUtil.utf8Str(decrypt)); - + String encryptHex = des.encryptHex(content); String decryptStr = des.decryptStr(encryptHex); - + Assert.assertEquals(content, decryptStr); } - + @Test public void vigenereTest() { String content = "Wherethereisawillthereisaway"; String key = "CompleteVictory"; - + String encrypt = Vigenere.encrypt(content, key); Assert.assertEquals("zXScRZ]KIOMhQjc0\\bYRXZOJK[Vi", encrypt); String decrypt = Vigenere.decrypt(encrypt, key); diff --git a/hutool-json/src/test/java/cn/hutool/json/IssueI3EGJP.java b/hutool-json/src/test/java/cn/hutool/json/IssueI3EGJP.java new file mode 100644 index 000000000..ba4fb2467 --- /dev/null +++ b/hutool-json/src/test/java/cn/hutool/json/IssueI3EGJP.java @@ -0,0 +1,26 @@ +package cn.hutool.json; + +import cn.hutool.core.bean.BeanUtil; +import lombok.Data; +import org.junit.Assert; +import org.junit.Test; + +public class IssueI3EGJP { + + @Test + public void hutoolMapToBean() { + JSONObject paramJson = new JSONObject(); + paramJson.set("is_booleana", "1"); + paramJson.set("is_booleanb", true); + ConvertDO convertDO = BeanUtil.toBean(paramJson, ConvertDO.class); + + Assert.assertTrue(convertDO.isBooleana()); + Assert.assertTrue(convertDO.getIsBooleanb()); + } + + @Data + public static class ConvertDO { + private boolean isBooleana; + private Boolean isBooleanb; + } +} diff --git a/hutool-poi/src/test/java/cn/hutool/poi/word/WordWriterTest.java b/hutool-poi/src/test/java/cn/hutool/poi/word/WordWriterTest.java index 220bc6c2c..5d056a262 100644 --- a/hutool-poi/src/test/java/cn/hutool/poi/word/WordWriterTest.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/word/WordWriterTest.java @@ -1,6 +1,7 @@ package cn.hutool.poi.word; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.ListUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.core.io.FileUtil; import cn.hutool.core.lang.Console; @@ -11,10 +12,11 @@ import java.awt.Font; import java.io.File; import java.util.ArrayList; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; public class WordWriterTest { - + @Test @Ignore public void writeTest() { @@ -82,4 +84,15 @@ public class WordWriterTest { // 关闭 writer.close(); } + + @Test + public void overflowTest(){ + final Word07Writer word07Writer = new Word07Writer(); + final List list = ListUtil.list(false); + final List list2 = ListUtil.list(false); + list.add("溢出测试"); + list2.add(list); + word07Writer.addTable(list); + word07Writer.close(); + } } diff --git a/hutool-system/src/test/java/cn/hutool/system/OshiTest.java b/hutool-system/src/test/java/cn/hutool/system/OshiTest.java index 74ceceff0..abe378729 100644 --- a/hutool-system/src/test/java/cn/hutool/system/OshiTest.java +++ b/hutool-system/src/test/java/cn/hutool/system/OshiTest.java @@ -6,9 +6,9 @@ import org.junit.Assert; import org.junit.Test; public class OshiTest { - + @Test - public void getMemeryTest() { + public void getMemoryTest() { long total = OshiUtil.getMemory().getTotal(); Assert.assertTrue(total > 0); }