Hex.java 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. /*
  2. * FileName:Hex.java
  3. * <p>
  4. * Copyright (c) 2017-2020, <a href="http://www.webcsn.com">hermit (794890569@qq.com)</a>.
  5. * <p>
  6. * Licensed under the GNU General Public License, Version 3 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. * <p>
  10. * http://www.gnu.org/licenses/gpl-3.0.html
  11. * <p>
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. *
  18. */
  19. package cn.com.lzt.common.util.security;
  20. import java.io.UnsupportedEncodingException;
  21. /**
  22. * Hex encoder and decoder. The charset used for certain operation can be set,
  23. * the default is set in
  24. *
  25. * @author ShenHuaJie
  26. * @version $Id: Hex.java, v 0.1 2014年3月25日 上午9:39:07 ShenHuaJie Exp $
  27. */
  28. public class Hex {
  29. /***
  30. * Default charset name is {@link CharEncoding#UTF_8}
  31. */
  32. public static final String DEFAULT_CHARSET_NAME = "UTF-8";
  33. /***
  34. * Used to build output as Hex
  35. */
  36. private static final char[] DIGITS_LOWER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
  37. 'e', 'f' };
  38. /***
  39. * Used to build output as Hex
  40. */
  41. private static final char[] DIGITS_UPPER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
  42. 'E', 'F' };
  43. /***
  44. * Converts an array of characters representing hexadecimal values into an
  45. * array of bytes of those same values. The returned array will be half the
  46. * length of the passed array, as it takes two characters to represent any
  47. * given byte. An exception is thrown if the passed char array has an odd
  48. * number of elements.
  49. *
  50. * @param data An array of characters containing hexadecimal digits
  51. * @return A byte array containing binary data decoded from the supplied
  52. * char array.
  53. * @throws Exception Thrown if an odd number or illegal of characters is
  54. * supplied
  55. */
  56. public static byte[] decodeHex(char[] data) throws Exception {
  57. int len = data.length;
  58. if ((len & 0x01) != 0) {
  59. throw new Exception("Odd number of characters.");
  60. }
  61. byte[] out = new byte[len >> 1];
  62. // two characters form the hex value.
  63. for (int i = 0, j = 0; j < len; i++) {
  64. int f = toDigit(data[j], j) << 4;
  65. j++;
  66. f = f | toDigit(data[j], j);
  67. j++;
  68. out[i] = (byte) (f & 0xFF);
  69. }
  70. return out;
  71. }
  72. /***
  73. * Converts an array of bytes into an array of characters representing the
  74. * hexadecimal values of each byte in order. The returned array will be
  75. * double the length of the passed array, as it takes two characters to
  76. * represent any given byte.
  77. *
  78. * @param data a byte[] to convert to Hex characters
  79. * @return A char[] containing hexadecimal characters
  80. */
  81. public static char[] encodeHex(byte[] data) {
  82. return encodeHex(data, true);
  83. }
  84. /***
  85. * Converts an array of bytes into an array of characters representing the
  86. * hexadecimal values of each byte in order. The returned array will be
  87. * double the length of the passed array, as it takes two characters to
  88. * represent any given byte.
  89. *
  90. * @param data a byte[] to convert to Hex characters
  91. * @param toLowerCase <code>true</code> converts to lowercase,
  92. * <code>false</code> to uppercase
  93. * @return A char[] containing hexadecimal characters
  94. * @since 1.4
  95. */
  96. public static char[] encodeHex(byte[] data, boolean toLowerCase) {
  97. return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
  98. }
  99. /***
  100. * Converts an array of bytes into an array of characters representing the
  101. * hexadecimal values of each byte in order. The returned array will be
  102. * double the length of the passed array, as it takes two characters to
  103. * represent any given byte.
  104. *
  105. * @param data a byte[] to convert to Hex characters
  106. * @param toDigits the output alphabet
  107. * @return A char[] containing hexadecimal characters
  108. * @since 1.4
  109. */
  110. protected static char[] encodeHex(byte[] data, char[] toDigits) {
  111. int l = data.length;
  112. char[] out = new char[l << 1];
  113. // two characters form the hex value.
  114. for (int i = 0, j = 0; i < l; i++) {
  115. out[j++] = toDigits[(0xF0 & data[i]) >>> 4];
  116. out[j++] = toDigits[0x0F & data[i]];
  117. }
  118. return out;
  119. }
  120. /***
  121. * Converts an array of bytes into a String representing the hexadecimal
  122. * values of each byte in order. The returned String will be double the
  123. * length of the passed array, as it takes two characters to represent any
  124. * given byte.
  125. *
  126. * @param data a byte[] to convert to Hex characters
  127. * @return A String containing hexadecimal characters
  128. * @since 1.4
  129. */
  130. public static String encodeHexString(byte[] data) {
  131. return new String(encodeHex(data));
  132. }
  133. /***
  134. * Converts a hexadecimal character to an integer.
  135. *
  136. * @param ch A character to convert to an integer digit
  137. * @param index The index of the character in the source
  138. * @return An integer
  139. * @throws Exception Thrown if ch is an illegal hex character
  140. */
  141. protected static int toDigit(char ch, int index) throws Exception {
  142. int digit = Character.digit(ch, 16);
  143. if (digit == -1) {
  144. throw new Exception("Illegal hexadecimal charcter " + ch + " at index " + index);
  145. }
  146. return digit;
  147. }
  148. private static String charsetName = DEFAULT_CHARSET_NAME;
  149. /***
  150. * Creates a new codec with the default charset name
  151. * {@link #DEFAULT_CHARSET_NAME}
  152. */
  153. public Hex() {
  154. }
  155. /***
  156. * Creates a new codec with the given charset name.
  157. *
  158. * @param csName the charset name.
  159. * @since 1.4
  160. */
  161. public Hex(String csName) {
  162. charsetName = csName;
  163. }
  164. /***
  165. * Converts an array of character bytes representing hexadecimal values into
  166. * an array of bytes of those same values. The returned array will be half
  167. * the length of the passed array, as it takes two characters to represent
  168. * any given byte. An exception is thrown if the passed char array has an
  169. * odd number of elements.
  170. *
  171. * @param array An array of character bytes containing hexadecimal digits
  172. * @return A byte array containing binary data decoded from the supplied
  173. * byte array (representing characters).
  174. * @throws Exception Thrown if an odd number of characters is supplied to
  175. * this function
  176. * @see #decodeHex(char[])
  177. */
  178. public byte[] decode(byte[] array) throws Exception {
  179. try {
  180. return decodeHex(new String(array, getCharsetName()).toCharArray());
  181. } catch (Exception e) {
  182. throw new Exception(e.getMessage(), e);
  183. }
  184. }
  185. /***
  186. * Converts a String or an array of character bytes representing hexadecimal
  187. * values into an array of bytes of those same values. The returned array
  188. * will be half the length of the passed String or array, as it takes two
  189. * characters to represent any given byte. An exception is thrown if the
  190. * passed char array has an odd number of elements.
  191. *
  192. * @param object A String or, an array of character bytes containing
  193. * hexadecimal digits
  194. * @return A byte array containing binary data decoded from the supplied
  195. * byte array (representing characters).
  196. * @throws Exception Thrown if an odd number of characters is supplied to
  197. * this function or the object is not a String or char[]
  198. * @see #decodeHex(char[])
  199. */
  200. public Object decode(Object object) throws Exception {
  201. try {
  202. char[] charArray = object instanceof String ? ((String) object).toCharArray() : (char[]) object;
  203. return decodeHex(charArray);
  204. } catch (ClassCastException e) {
  205. throw new Exception(e.getMessage(), e);
  206. }
  207. }
  208. /***
  209. * Converts an array of bytes into an array of bytes for the characters
  210. * representing the hexadecimal values of each byte in order. The returned
  211. * array will be double the length of the passed array, as it takes two
  212. * characters to represent any given byte.
  213. * <p>
  214. * The conversion from hexadecimal characters to the returned bytes is
  215. * performed with the charset named by {@link #getCharsetName()}.
  216. * </p>
  217. *
  218. * @param array a byte[] to convert to Hex characters
  219. * @return A byte[] containing the bytes of the hexadecimal characters
  220. * @throws IllegalStateException if the charsetName is invalid. This API
  221. * throws {@link IllegalStateException} instead of
  222. * {@link Exception} for backward compatibility.
  223. * @see #encodeHex(byte[])
  224. */
  225. public static byte[] encode(byte[] array) throws UnsupportedEncodingException {
  226. String string = encodeHexString(array);
  227. if (string == null) {
  228. return null;
  229. }
  230. return string.getBytes(charsetName);
  231. }
  232. /***
  233. * Converts a String or an array of bytes into an array of characters
  234. * representing the hexadecimal values of each byte in order. The returned
  235. * array will be double the length of the passed String or array, as it
  236. * takes two characters to represent any given byte.
  237. * <p>
  238. * The conversion from hexadecimal characters to bytes to be encoded to
  239. * performed with the charset named by {@link #getCharsetName()}.
  240. * </p>
  241. *
  242. * @param object a String, or byte[] to convert to Hex characters
  243. * @return A char[] containing hexadecimal characters
  244. * @throws Exception Thrown if the given object is not a String or byte[]
  245. * @see #encodeHex(byte[])
  246. */
  247. public Object encode(Object object) throws Exception {
  248. try {
  249. byte[] byteArray = object instanceof String ? ((String) object).getBytes(getCharsetName())
  250. : (byte[]) object;
  251. return encodeHex(byteArray);
  252. } catch (ClassCastException e) {
  253. throw new Exception(e.getMessage(), e);
  254. } catch (Exception e) {
  255. throw new Exception(e.getMessage(), e);
  256. }
  257. }
  258. /***
  259. * Gets the charset name.
  260. *
  261. * @return the charset name.
  262. * @since 1.4
  263. */
  264. public String getCharsetName() {
  265. return charsetName;
  266. }
  267. /***
  268. * Returns a string representation of the object, which includes the charset
  269. * name.
  270. *
  271. * @return a string representation of the object.
  272. */
  273. public String toString() {
  274. return super.toString() + "[charsetName=" + charsetName + "]";
  275. }
  276. }