diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/Base16Codec.java b/hutool-core/src/main/java/cn/hutool/core/codec/Base16Codec.java
new file mode 100644
index 000000000..14499d153
--- /dev/null
+++ b/hutool-core/src/main/java/cn/hutool/core/codec/Base16Codec.java
@@ -0,0 +1,118 @@
+package cn.hutool.core.codec;
+
+import cn.hutool.core.exceptions.UtilException;
+import cn.hutool.core.util.StrUtil;
+
+/**
+ * Base16(Hex)编码解码器
+ * 十六进制(简写为hex或下标16)在数学中是一种逢16进1的进位制,一般用数字0到9和字母A到F表示(其中:A~F即10~15)。
+ * 例如十进制数57,在二进制写作111001,在16进制写作39。
+ *
+ * @author looly
+ * @since 5.7.23
+ */
+public class Base16Codec implements Encoder, Decoder {
+
+ public static final Base16Codec CODEC_LOWER = new Base16Codec(true);
+ public static final Base16Codec CODEC_UPPER = new Base16Codec(false);
+
+ private final char[] alphabets;
+
+ /**
+ * 构造
+ *
+ * @param lowerCase 是否小写
+ */
+ public Base16Codec(boolean lowerCase) {
+ this.alphabets = (lowerCase ? "0123456789abcdef" : "0123456789ABCDEF").toCharArray();
+ }
+
+ @Override
+ public char[] encode(byte[] data) {
+ final int len = data.length;
+ final char[] out = new char[len << 1];//len*2
+ // two characters from the hex value.
+ for (int i = 0, j = 0; i < len; i++) {
+ out[j++] = alphabets[(0xF0 & data[i]) >>> 4];// 高位
+ out[j++] = alphabets[0x0F & data[i]];// 低位
+ }
+ return out;
+ }
+
+ @Override
+ public byte[] decode(CharSequence encoded) {
+ if (StrUtil.isEmpty(encoded)) {
+ return null;
+ }
+
+ encoded = StrUtil.cleanBlank(encoded);
+ int len = encoded.length();
+
+ if ((len & 0x01) != 0) {
+ // 如果提供的数据是奇数长度,则前面补0凑偶数
+ encoded = "0" + encoded;
+ len = encoded.length();
+ }
+
+ final byte[] out = new byte[len >> 1];
+
+ // two characters form the hex value.
+ for (int i = 0, j = 0; j < len; i++) {
+ int f = toDigit(encoded.charAt(j), j) << 4;
+ j++;
+ f = f | toDigit(encoded.charAt(j), j);
+ j++;
+ out[i] = (byte) (f & 0xFF);
+ }
+
+ return out;
+ }
+
+ /**
+ * 将指定char值转换为Unicode字符串形式,常用于特殊字符(例如汉字)转Unicode形式
+ * 转换的字符串如果u后不足4位,则前面用0填充,例如:
+ *
+ *
+ * '你' =》'\u4f60'
+ *
+ *
+ * @param ch char值
+ * @return Unicode表现形式
+ */
+ public String toUnicodeHex(char ch) {
+ return "\\u" +//
+ alphabets[(ch >> 12) & 15] +//
+ alphabets[(ch >> 8) & 15] +//
+ alphabets[(ch >> 4) & 15] +//
+ alphabets[(ch) & 15];
+ }
+
+ /**
+ * 将byte值转为16进制并添加到{@link StringBuilder}中
+ *
+ * @param builder {@link StringBuilder}
+ * @param b byte
+ */
+ public void appendHex(StringBuilder builder, byte b) {
+ int high = (b & 0xf0) >>> 4;//高位
+ int low = b & 0x0f;//低位
+ builder.append(alphabets[high]);
+ builder.append(alphabets[low]);
+ }
+
+ /**
+ * 将十六进制字符转换成一个整数
+ *
+ * @param ch 十六进制char
+ * @param index 十六进制字符在字符数组中的位置
+ * @return 一个整数
+ * @throws UtilException 当ch不是一个合法的十六进制字符时,抛出运行时异常
+ */
+ private static int toDigit(char ch, int index) {
+ int digit = Character.digit(ch, 16);
+ if (digit < 0) {
+ throw new UtilException("Illegal hexadecimal character {} at index {}", ch, index);
+ }
+ return digit;
+ }
+}
diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/Base62Codec.java b/hutool-core/src/main/java/cn/hutool/core/codec/Base62Codec.java
index 2386de005..0561e0a70 100644
--- a/hutool-core/src/main/java/cn/hutool/core/codec/Base62Codec.java
+++ b/hutool-core/src/main/java/cn/hutool/core/codec/Base62Codec.java
@@ -83,12 +83,12 @@ public class Base62Codec implements Encoder, Decoder {
/**
* 执行解码
*
- * @param data 被解码的数据
+ * @param encoded 被解码的数据
* @return 解码后的数据
*/
- R decode(T data);
+ R decode(T encoded);
}
diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/Encoder.java b/hutool-core/src/main/java/cn/hutool/core/codec/Encoder.java
index ca05d0ac3..9cc728d72 100644
--- a/hutool-core/src/main/java/cn/hutool/core/codec/Encoder.java
+++ b/hutool-core/src/main/java/cn/hutool/core/codec/Encoder.java
@@ -13,8 +13,8 @@ public interface Encoder {
/**
* 执行编码
*
- * @param encoded 被编码的数据
+ * @param data 被编码的数据
* @return 编码后的数据
*/
- R encode(T encoded);
+ R encode(T data);
}
diff --git a/hutool-core/src/main/java/cn/hutool/core/util/HexUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/HexUtil.java
index 1d9ec7cc5..a83f29e66 100644
--- a/hutool-core/src/main/java/cn/hutool/core/util/HexUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/util/HexUtil.java
@@ -1,5 +1,6 @@
package cn.hutool.core.util;
+import cn.hutool.core.codec.Base16Codec;
import cn.hutool.core.exceptions.UtilException;
import java.awt.Color;
@@ -17,15 +18,6 @@ import java.nio.charset.Charset;
*/
public class HexUtil {
- /**
- * 用于建立十六进制字符的输出的小写字符数组
- */
- private static final char[] DIGITS_LOWER = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
- /**
- * 用于建立十六进制字符的输出的大写字符数组
- */
- private static final char[] DIGITS_UPPER = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
-
/**
* 判断给定字符串是否为16进制数
* 如果是,需要使用对应数字类型对象的{@code decode}方法解码
@@ -80,7 +72,7 @@ public class HexUtil {
* @return 十六进制char[]
*/
public static char[] encodeHex(byte[] data, boolean toLowerCase) {
- return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
+ return (toLowerCase ? Base16Codec.CODEC_LOWER : Base16Codec.CODEC_UPPER).encode(data);
}
/**
@@ -122,7 +114,7 @@ public class HexUtil {
* @return 十六进制String
*/
public static String encodeHexStr(byte[] data, boolean toLowerCase) {
- return encodeHexStr(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
+ return new String(encodeHex(data, toLowerCase));
}
// ---------------------------------------------------------------------------------------------------- decode
@@ -192,31 +184,7 @@ public class HexUtil {
* @since 5.6.6
*/
public static byte[] decodeHex(CharSequence hexData) {
- if (StrUtil.isEmpty(hexData)) {
- return null;
- }
-
- hexData = StrUtil.cleanBlank(hexData);
- int len = hexData.length();
-
- if ((len & 0x01) != 0) {
- hexData = "0" + hexData;
- len = hexData.length();
-// throw new UtilException("Odd number of characters.");
- }
-
- final byte[] out = new byte[len >> 1];
-
- // two characters form the hex value.
- for (int i = 0, j = 0; j < len; i++) {
- int f = toDigit(hexData.charAt(j), j) << 4;
- j++;
- f = f | toDigit(hexData.charAt(j), j);
- j++;
- out[i] = (byte) (f & 0xFF);
- }
-
- return out;
+ return Base16Codec.CODEC_LOWER.decode(hexData);
}
// ---------------------------------------------------------------------------------------- Color
@@ -310,11 +278,7 @@ public class HexUtil {
* @since 4.0.1
*/
public static String toUnicodeHex(char ch) {
- return "\\u" +//
- DIGITS_LOWER[(ch >> 12) & 15] +//
- DIGITS_LOWER[(ch >> 8) & 15] +//
- DIGITS_LOWER[(ch >> 4) & 15] +//
- DIGITS_LOWER[(ch) & 15];
+ return Base16Codec.CODEC_LOWER.toUnicodeHex(ch);
}
/**
@@ -370,12 +334,7 @@ public class HexUtil {
* @since 4.4.1
*/
public static void appendHex(StringBuilder builder, byte b, boolean toLowerCase) {
- final char[] toDigits = toLowerCase ? DIGITS_LOWER : DIGITS_UPPER;
-
- int high = (b & 0xf0) >>> 4;//高位
- int low = b & 0x0f;//低位
- builder.append(toDigits[high]);
- builder.append(toDigits[low]);
+ (toLowerCase ? Base16Codec.CODEC_LOWER : Base16Codec.CODEC_UPPER).appendHex(builder, b);
}
/**
@@ -411,51 +370,4 @@ public class HexUtil {
return builder.toString();
}
- // ---------------------------------------------------------------------------------------- Private method start
-
- /**
- * 将字节数组转换为十六进制字符串
- *
- * @param data byte[]
- * @param toDigits 用于控制输出的char[]
- * @return 十六进制String
- */
- private static String encodeHexStr(byte[] data, char[] toDigits) {
- return new String(encodeHex(data, toDigits));
- }
-
- /**
- * 将字节数组转换为十六进制字符数组
- *
- * @param data byte[]
- * @param toDigits 用于控制输出的char[]
- * @return 十六进制char[]
- */
- private static char[] encodeHex(byte[] data, char[] toDigits) {
- final int len = data.length;
- final char[] out = new char[len << 1];//len*2
- // two characters from the hex value.
- for (int i = 0, j = 0; i < len; i++) {
- out[j++] = toDigits[(0xF0 & data[i]) >>> 4];// 高位
- out[j++] = toDigits[0x0F & data[i]];// 低位
- }
- return out;
- }
-
- /**
- * 将十六进制字符转换成一个整数
- *
- * @param ch 十六进制char
- * @param index 十六进制字符在字符数组中的位置
- * @return 一个整数
- * @throws UtilException 当ch不是一个合法的十六进制字符时,抛出运行时异常
- */
- private static int toDigit(char ch, int index) {
- int digit = Character.digit(ch, 16);
- if (digit < 0) {
- throw new UtilException("Illegal hexadecimal character {} at index {}", ch, index);
- }
- return digit;
- }
- // ---------------------------------------------------------------------------------------- Private method end
}