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));