1+ package com .reachauto .hkr .tennis .ft1 ;
2+
3+ import com .aliyun .openservices .shade .io .netty .util .CharsetUtil ;
4+
5+ import java .awt .*;
6+ import java .nio .charset .Charset ;
7+
8+ /**
9+ * 十六进制(简写为hex或下标16)在数学中是一种逢16进1的进位制,一般用数字0到9和字母A到F表示(其中:A~F即10~15)。<br>
10+ * 例如十进制数57,在二进制写作111001,在16进制写作39。<br>
11+ * 像java,c这样的语言为了区分十六进制和十进制数值,会在十六进制数的前面加上 0x,比如0x20是十进制的32,而不是十进制的20<br>
12+ * <p>
13+ * 参考:https://my.oschina.net/xinxingegeya/blog/287476
14+ *
15+ * @author Looly
16+ */
17+ public class HexTool {
18+
19+ /**
20+ * 用于建立十六进制字符的输出的小写字符数组
21+ */
22+ private static final char [] DIGITS_LOWER = {'0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , 'a' , 'b' , 'c' , 'd' , 'e' , 'f' };
23+ /**
24+ * 用于建立十六进制字符的输出的大写字符数组
25+ */
26+ private static final char [] DIGITS_UPPER = {'0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , 'A' , 'B' , 'C' , 'D' , 'E' , 'F' };
27+
28+ /**
29+ * 判断给定字符串是否为16进制数<br>
30+ * 如果是,需要使用对应数字类型对象的<code>decode</code>方法解码<br>
31+ * 例如:{@code Integer.decode}方法解码int类型的16进制数字
32+ *
33+ * @param value 值
34+ * @return 是否为16进制
35+ */
36+ public static boolean isHexNumber (String value ) {
37+ int index = (value .startsWith ("-" ) ? 1 : 0 );
38+ return (value .startsWith ("0x" , index ) || value .startsWith ("0X" , index ) || value .startsWith ("#" , index ));
39+ }
40+
41+ // ---------------------------------------------------------------------------------------------------- encode
42+
43+ /**
44+ * 将字节数组转换为十六进制字符数组
45+ *
46+ * @param data byte[]
47+ * @return 十六进制char[]
48+ */
49+ public static char [] encodeHex (byte [] data ) {
50+ return encodeHex (data , true );
51+ }
52+
53+ /**
54+ * 将字节数组转换为十六进制字符数组
55+ *
56+ * @param str 字符串
57+ * @param charset 编码
58+ * @return 十六进制char[]
59+ */
60+ public static char [] encodeHex (String str , Charset charset ) {
61+ return encodeHex (StringTool .bytes (str , charset ), true );
62+ }
63+
64+ /**
65+ * 将字节数组转换为十六进制字符数组
66+ *
67+ * @param data byte[]
68+ * @param toLowerCase <code>true</code> 传换成小写格式 , <code>false</code> 传换成大写格式
69+ * @return 十六进制char[]
70+ */
71+ public static char [] encodeHex (byte [] data , boolean toLowerCase ) {
72+ return encodeHex (data , toLowerCase ? DIGITS_LOWER : DIGITS_UPPER );
73+ }
74+
75+ /**
76+ * 将字节数组转换为十六进制字符串
77+ *
78+ * @param data byte[]
79+ * @return 十六进制String
80+ */
81+ public static String encodeHexStr (byte [] data ) {
82+ return encodeHexStr (data , true );
83+ }
84+
85+ /**
86+ * 将字节数组转换为十六进制字符串,结果为小写
87+ *
88+ * @param data 被编码的字符串
89+ * @param charset 编码
90+ * @return 十六进制String
91+ */
92+ public static String encodeHexStr (String data , Charset charset ) {
93+ return encodeHexStr (StringTool .bytes (data , charset ), true );
94+ }
95+
96+ /**
97+ * 将字节数组转换为十六进制字符串,结果为小写,默认编码是UTF-8
98+ *
99+ * @param data 被编码的字符串
100+ * @return 十六进制String
101+ */
102+ public static String encodeHexStr (String data ) {
103+ return encodeHexStr (data , CharsetUtil .UTF_8 );
104+ }
105+
106+ /**
107+ * 将字节数组转换为十六进制字符串
108+ *
109+ * @param data byte[]
110+ * @param toLowerCase <code>true</code> 传换成小写格式 , <code>false</code> 传换成大写格式
111+ * @return 十六进制String
112+ */
113+ public static String encodeHexStr (byte [] data , boolean toLowerCase ) {
114+ return encodeHexStr (data , toLowerCase ? DIGITS_LOWER : DIGITS_UPPER );
115+ }
116+
117+ // ---------------------------------------------------------------------------------------------------- decode
118+
119+ /**
120+ * 将十六进制字符数组转换为字符串,默认编码UTF-8
121+ *
122+ * @param hexStr 十六进制String
123+ * @return 字符串
124+ */
125+ public static String decodeHexStr (String hexStr ) {
126+ return decodeHexStr (hexStr , CharsetUtil .UTF_8 );
127+ }
128+
129+ /**
130+ * 将十六进制字符数组转换为字符串
131+ *
132+ * @param hexStr 十六进制String
133+ * @param charset 编码
134+ * @return 字符串
135+ */
136+ public static String decodeHexStr (String hexStr , Charset charset ) {
137+ if (StringTool .isEmpty (hexStr )) {
138+ return hexStr ;
139+ }
140+ return decodeHexStr (hexStr .toCharArray (), charset );
141+ }
142+
143+ /**
144+ * 将十六进制字符数组转换为字符串
145+ *
146+ * @param hexData 十六进制char[]
147+ * @param charset 编码
148+ * @return 字符串
149+ */
150+ public static String decodeHexStr (char [] hexData , Charset charset ) {
151+ return StringTool .str (decodeHex (hexData ), charset );
152+ }
153+
154+ /**
155+ * 将十六进制字符数组转换为字节数组
156+ *
157+ * @param hexData 十六进制char[]
158+ * @return byte[]
159+ * @throws RuntimeException 如果源十六进制字符数组是一个奇怪的长度,将抛出运行时异常
160+ */
161+ public static byte [] decodeHex (char [] hexData ) {
162+
163+ int len = hexData .length ;
164+
165+ if ((len & 0x01 ) != 0 ) {
166+ throw new RuntimeException ("Odd number of characters." );
167+ }
168+
169+ byte [] out = new byte [len >> 1 ];
170+
171+ // two characters form the hex value.
172+ for (int i = 0 , j = 0 ; j < len ; i ++) {
173+ int f = toDigit (hexData [j ], j ) << 4 ;
174+ j ++;
175+ f = f | toDigit (hexData [j ], j );
176+ j ++;
177+ out [i ] = (byte ) (f & 0xFF );
178+ }
179+
180+ return out ;
181+ }
182+
183+ /**
184+ * 将十六进制字符串解码为byte[]
185+ *
186+ * @param hexStr 十六进制String
187+ * @return byte[]
188+ */
189+ public static byte [] decodeHex (String hexStr ) {
190+ if (StringTool .isEmpty (hexStr )) {
191+ return null ;
192+ }
193+ return decodeHex (hexStr .toCharArray ());
194+ }
195+
196+ // ---------------------------------------------------------------------------------------- Color
197+
198+ /**
199+ * 将{@link Color}编码为Hex形式
200+ *
201+ * @param color {@link Color}
202+ * @return Hex字符串
203+ * @since 3.0.8
204+ */
205+ public static String encodeColor (Color color ) {
206+ return encodeColor (color , "#" );
207+ }
208+
209+ /**
210+ * 将{@link Color}编码为Hex形式
211+ *
212+ * @param color {@link Color}
213+ * @param prefix 前缀字符串,可以是#、0x等
214+ * @return Hex字符串
215+ * @since 3.0.8
216+ */
217+ public static String encodeColor (Color color , String prefix ) {
218+ final StringBuffer builder = new StringBuffer (prefix );
219+ String colorHex ;
220+ colorHex = Integer .toHexString (color .getRed ());
221+ if (1 == colorHex .length ()) {
222+ builder .append ('0' );
223+ }
224+ builder .append (colorHex );
225+ colorHex = Integer .toHexString (color .getGreen ());
226+ if (1 == colorHex .length ()) {
227+ builder .append ('0' );
228+ }
229+ builder .append (colorHex );
230+ colorHex = Integer .toHexString (color .getBlue ());
231+ if (1 == colorHex .length ()) {
232+ builder .append ('0' );
233+ }
234+ builder .append (colorHex );
235+ return builder .toString ();
236+ }
237+
238+ /**
239+ * 将Hex颜色值转为
240+ *
241+ * @param hexColor 16进制颜色值,可以以#开头,也可以用0x开头
242+ * @return {@link Color}
243+ * @since 3.0.8
244+ */
245+ public static Color decodeColor (String hexColor ) {
246+ return Color .decode (hexColor );
247+ }
248+
249+ // ---------------------------------------------------------------------------------------- Private method start
250+
251+ /**
252+ * 将字节数组转换为十六进制字符串
253+ *
254+ * @param data byte[]
255+ * @param toDigits 用于控制输出的char[]
256+ * @return 十六进制String
257+ */
258+ private static String encodeHexStr (byte [] data , char [] toDigits ) {
259+ return new String (encodeHex (data , toDigits ));
260+ }
261+
262+ /**
263+ * 将字节数组转换为十六进制字符数组
264+ *
265+ * @param data byte[]
266+ * @param toDigits 用于控制输出的char[]
267+ * @return 十六进制char[]
268+ */
269+ private static char [] encodeHex (byte [] data , char [] toDigits ) {
270+ int l = data .length ;
271+ char [] out = new char [l << 1 ];
272+ // two characters from the hex value.
273+ for (int i = 0 , j = 0 ; i < l ; i ++) {
274+ out [j ++] = toDigits [(0xF0 & data [i ]) >>> 4 ];
275+ out [j ++] = toDigits [0x0F & data [i ]];
276+ }
277+ return out ;
278+ }
279+
280+ /**
281+ * 将十六进制字符转换成一个整数
282+ *
283+ * @param ch 十六进制char
284+ * @param index 十六进制字符在字符数组中的位置
285+ * @return 一个整数
286+ * @throws RuntimeException 当ch不是一个合法的十六进制字符时,抛出运行时异常
287+ */
288+ private static int toDigit (char ch , int index ) {
289+ int digit = Character .digit (ch , 16 );
290+ if (digit == -1 ) {
291+ throw new RuntimeException ("Illegal hexadecimal character " + ch + " at index " + index );
292+ }
293+ return digit ;
294+ }
295+ // ---------------------------------------------------------------------------------------- Private method end
296+ }
0 commit comments