From 7b4fd66d813dcb30e210bea59a9b085bc68963f4 Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 18 Mar 2022 01:02:31 +0800 Subject: [PATCH] add Base16Codec --- .../cn/hutool/core/codec/Base16Codec.java | 118 ++++++++++++++++++ .../cn/hutool/core/codec/Base62Codec.java | 6 +- .../java/cn/hutool/core/codec/Base64.java | 31 +++-- .../java/cn/hutool/core/codec/Decoder.java | 4 +- .../java/cn/hutool/core/codec/Encoder.java | 4 +- .../java/cn/hutool/core/util/HexUtil.java | 100 +-------------- 6 files changed, 150 insertions(+), 113 deletions(-) create mode 100644 hutool-core/src/main/java/cn/hutool/core/codec/Base16Codec.java 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 }