From 7c01feece90134eb480d84afac17500e02d9c09e Mon Sep 17 00:00:00 2001 From: FULaBUla <46469068+FULaBUla@users.noreply.github.com> Date: Sun, 28 Mar 2021 23:04:18 +0800 Subject: [PATCH] =?UTF-8?q?Refactor=20(hutool-core):=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E6=95=B0=E5=AD=97=E8=BD=AC=E6=8D=A2=E7=9A=84=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=EF=BC=8C=E5=A2=9E=E5=8A=A0=E6=8C=89=E7=85=A7=E6=8C=87=E5=AE=9A?= =?UTF-8?q?=E7=AB=AF=E5=BA=8F=E8=BD=AC=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # 修改 1. 因为跨平台通信时由于平台原因存在字节序不一致的情况,所以在对数据进行转换的时候需要指定端序,按照两边的约定选择是使用大端序还是小端序,因此重构原有 int、short 和 long 与 byte[] 之间互相转换的实现,增加可以指定转换方式,补充大端序转换实现,同时保留原有方法,默认设置为小端序转换。 2. 将部分魔法值使用常量进行替代 3. 对于实现的修改,补充了测试方法的实现,完成不同端序的转换测试 --- .../java/cn/hutool/core/convert/Convert.java | 206 ++++++++++++++---- .../cn/hutool/core/convert/ConvertTest.java | 89 +++++++- 2 files changed, 253 insertions(+), 42 deletions(-) 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..031d62091 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 @@ -14,16 +14,11 @@ import cn.hutool.core.util.StrUtil; import java.lang.reflect.Type; import java.math.BigDecimal; import java.math.BigInteger; +import java.nio.ByteOrder; import java.nio.charset.Charset; import java.time.Instant; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.concurrent.TimeUnit; /** @@ -1044,92 +1039,223 @@ 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 bytesToShort(bytes, ByteOrder.LITTLE_ENDIAN); } /** - * short转byte数组 + * byte数组转short
+ * 自定义端序 + * + * @param bytes byte数组 + * @param byteOrder 端序 + * @return short值 + * @since 5.6.3 + */ + 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数组 - * @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 shortToBytes(shortValue, ByteOrder.LITTLE_ENDIAN); + } + + /** + * short转byte数组
+ * 自定义端序 + * + * @param shortValue short值 + * @param byteOrder 端序 + * @return byte数组 + * @since 5.6.3 + */ + 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值 + * 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 bytesToInt(bytes, ByteOrder.LITTLE_ENDIAN); } /** - * int转byte数组 + * byte[]转int值
+ * 自定义端序 + * + * @param bytes byte数组 + * @param byteOrder 端序 + * @return int值 + * @since 5.6.3 + */ + 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数组 - * @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 intToBytes(intValue, ByteOrder.LITTLE_ENDIAN); + } + + /** + * int转byte数组
+ * 自定义端序 + * + * @param intValue int值 + * @param byteOrder 端序 + * @return byte数组 + * @since 5.6.3 + */ + 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数组 - * @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 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数组 + * @since 5.6.3 + */ + 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值 - * @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 + 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值 + * @since 5.6.3 + */ + public static long bytesToLong(byte[] bytes, ByteOrder byteOrder) { long values = 0; - for (int i = 0; i < 8; i++) { - values <<= 8; - values |= (bytes[i] & 0xff); + 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; } } 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..e2e0b23fb 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 @@ -10,6 +10,7 @@ import org.junit.Assert; import org.junit.Test; import java.io.Serializable; +import java.nio.ByteOrder; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; @@ -173,6 +174,35 @@ public class ConvertTest { Assert.assertEquals(int2, int3); } + @Test + public void intAndBytesLittleEndianTest() { + // 测试 int 转小端序 byte 数组 + int int1 = 1417; + + byte[] bytesInt = Convert.intToBytes(int1, ByteOrder.LITTLE_ENDIAN); + int int2 = Convert.bytesToInt(bytesInt, ByteOrder.LITTLE_ENDIAN); + Assert.assertEquals(int1, int2); + + byte[] bytesInt2 = Convert.intToBytes(int1, ByteOrder.LITTLE_ENDIAN); + int int3 = Convert.bytesToInt(bytesInt2, ByteOrder.LITTLE_ENDIAN); + Assert.assertEquals(int1, int3); + + byte[] bytesInt3 = Convert.intToBytes(int1, ByteOrder.LITTLE_ENDIAN); + int int4 = Convert.bytesToInt(bytesInt3, ByteOrder.LITTLE_ENDIAN); + Assert.assertEquals(int1, int4); + } + + @Test + public void intAndBytesBigEndianTest() { + // 测试 int 转大端序 byte 数组 + int int2 = 1417; + byte[] bytesInt = Convert.intToBytes(int2, ByteOrder.BIG_ENDIAN); + + // 测试大端序 byte 数组转 int + int int3 = Convert.bytesToInt(bytesInt, ByteOrder.BIG_ENDIAN); + Assert.assertEquals(int2, int3); + } + @Test public void longAndBytesTest() { // 测试 long 转 byte 数组 @@ -184,6 +214,35 @@ public class ConvertTest { Assert.assertEquals(long1, long2); } + @Test + public void longAndBytesLittleEndianTest() { + // 测试 long 转 byte 数组 + long long1 = 2223; + + byte[] bytesLong = Convert.longToBytes(long1, ByteOrder.LITTLE_ENDIAN); + long long2 = Convert.bytesToLong(bytesLong, ByteOrder.LITTLE_ENDIAN); + Assert.assertEquals(long1, long2); + + byte[] bytesLong2 = Convert.longToBytes(long1); + long long3 = Convert.bytesToLong(bytesLong2, ByteOrder.LITTLE_ENDIAN); + Assert.assertEquals(long1, long3); + + byte[] bytesLong3 = Convert.longToBytes(long1, ByteOrder.LITTLE_ENDIAN); + long long4 = Convert.bytesToLong(bytesLong3); + Assert.assertEquals(long1, long4); + } + + @Test + public void longAndBytesBigEndianTest() { + // 测试大端序 long 转 byte 数组 + long long1 = 2223; + + byte[] bytesLong = Convert.longToBytes(long1, ByteOrder.BIG_ENDIAN); + long long2 = Convert.bytesToLong(bytesLong, ByteOrder.BIG_ENDIAN); + + Assert.assertEquals(long1, long2); + } + @Test public void shortAndBytesTest() { short short1 = 122; @@ -194,8 +253,34 @@ public class ConvertTest { } @Test - public void toListTest(){ - List list = Arrays.asList("1","2"); + public void shortAndBytesLittleEndianTest() { + short short1 = 122; + + byte[] bytes = Convert.shortToBytes(short1, ByteOrder.LITTLE_ENDIAN); + short short2 = Convert.bytesToShort(bytes, ByteOrder.LITTLE_ENDIAN); + Assert.assertEquals(short2, short1); + + byte[] bytes2 = Convert.shortToBytes(short1); + short short3 = Convert.bytesToShort(bytes2, ByteOrder.LITTLE_ENDIAN); + Assert.assertEquals(short3, short1); + + byte[] bytes3 = Convert.shortToBytes(short1, ByteOrder.LITTLE_ENDIAN); + short short4 = Convert.bytesToShort(bytes3); + Assert.assertEquals(short4, short1); + } + + @Test + public void shortAndBytesBigEndianTest() { + short short1 = 122; + byte[] bytes = Convert.shortToBytes(short1, ByteOrder.BIG_ENDIAN); + short short2 = Convert.bytesToShort(bytes, ByteOrder.BIG_ENDIAN); + + Assert.assertEquals(short2, short1); + } + + @Test + 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));