@@ -45,6 +45,62 @@ public final class HexUtil {
4545 NEW_LINE = newLine ;
4646 }
4747
48+ private static final char [] HEX_CODES = "0123456789ABCDEF" .toCharArray ();
49+
50+ /**
51+ * Converts an array of bytes into a string.
52+ *
53+ * @param bytes an array of bytes
54+ *
55+ * @return a string containing a lexical representation of HEX binary
56+ *
57+ * @throws NullpointerException if {@code bytes} is null.
58+ *
59+ * @since 1.16.1
60+ */
61+ public static String toHexString (@ NonNull byte [] bytes ) {
62+ val result = new StringBuilder (bytes .length * 2 );
63+ for (val value : bytes ) {
64+ result .append (HEX_CODES [(value >> 4 ) & 0xF ]);
65+ result .append (HEX_CODES [value & 0xF ]);
66+ }
67+ return result .toString ();
68+ }
69+
70+ /**
71+ * Converts the string argument into an array of bytes.
72+ *
73+ * @param string a string containing lexical representation of HEX binary.
74+ *
75+ * @return an array of bytes represented by the string argument.
76+ *
77+ * @throws NullpointerException if {@code string} is null.
78+ *
79+ * @throws IllegalArgumentException if string parameter does not conform to lexical
80+ * value space defined for HEX binary.
81+ *
82+ * @since 1.16.1
83+ */
84+ public static byte [] toByteArray (@ NonNull String string ) {
85+ val length = string .length ();
86+ if (length % 2 != 0 ) {
87+ val msg = String .format (ENGLISH , "hexBinary needs to be even-length: %s" , string );
88+ throw new IllegalArgumentException (msg );
89+ }
90+
91+ val result = new byte [length / 2 ];
92+ for (int index = 0 ; index < length ; index += 2 ) {
93+ int hight = hexToBin (string .charAt (index ));
94+ int low = hexToBin (string .charAt (index + 1 ));
95+ if (hight == -1 || low == -1 ) {
96+ val msg = String .format (ENGLISH , "contains illegal character for hexBinary: %s" , string );
97+ throw new IllegalArgumentException (msg );
98+ }
99+ result [index / 2 ] = (byte ) (hight * 16 + low );
100+ }
101+ return result ;
102+ }
103+
48104 /**
49105 * Converts an integer value into two-chars string with leading 0.
50106 *
@@ -133,10 +189,9 @@ public static String prettyHexDump (@NonNull Bytes buffer, int offset, int lengt
133189 for (int index = 0 ; index < limit ; index ++) {
134190 val value = buffer .getUnsignedByte (rowStartIndex + index );
135191
136- val hex = byteToHex (value );
137192 val hexIndex = 1 + 3 * index ;
138- hexDump .setCharAt (hexIndex , hex . charAt ( 0 ) );
139- hexDump .setCharAt (hexIndex + 1 , hex . charAt ( 1 ) );
193+ hexDump .setCharAt (hexIndex , HEX_CODES [( value >> 4 ) & 0xF ] );
194+ hexDump .setCharAt (hexIndex + 1 , HEX_CODES [ value & 0xF ] );
140195
141196 asciiDump .setCharAt (index , byteToChar (value ));
142197 }
@@ -150,6 +205,17 @@ public static String prettyHexDump (@NonNull Bytes buffer, int offset, int lengt
150205 .toString ();
151206 }
152207
208+ private static int hexToBin (char character ) {
209+ if (Character .isDigit (character )) {
210+ return character - '0' ;
211+ }
212+
213+ val letter = Character .toUpperCase (character );
214+ return 'A' <= letter && letter <= 'F'
215+ ? letter - 'A' + 10
216+ : -1 ;
217+ }
218+
153219 private HexUtil () {
154220 throw new UnsupportedOperationException ();
155221 }
0 commit comments