All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.seppiko.commons.utils.codec.HexUtil Maven / Gradle / Ivy

There is a newer version: 2.11.0
Show newest version
/*
 * Copyright 2023 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.seppiko.commons.utils.codec;

import java.io.Serial;
import java.io.Serializable;
import org.seppiko.commons.utils.StringUtil;

/**
 * Hexadecimal Encoder / Decoder Util.
 *
 * @author Leonard Woo
 */
public class HexUtil implements Serializable {

  @Serial
  private static final long serialVersionUID = -6597436615085466807L;

  private HexUtil() {}

  /** Hexadecimal length */
  public static final int HEXADECIMAL_LENGTH = 16;

  /** Hexadecimal character array with lower letters */
  public static final char[] HEXADECIMAL = {
      '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
      'a', 'b', 'c', 'd', 'e', 'f'
  };

  /** Hexadecimal character array with upper letters */
  public static final char[] HEXADECIMAL_UPPER = {
      '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
      'A', 'B', 'C', 'D', 'E', 'F'
  };

  /** Hexadecimal decode table and ignore case */
  public static final byte[] HEXADECIMAL_DECODE_TABLE = {
   //  0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 00-0f
      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 10-1f
      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 20-2f
       0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1, // 30-3f 0-9
      -1, 10, 11, 12, 13, 14, 15,                                     // 40-46 A-F
                                  -1, -1, -1, -1, -1, -1, -1, -1, -1, // 47-4f
      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 50-5f
      -1, 10, 11, 12, 13, 14, 15                                      // 60-66 a-f
  };

  /**
   * convert byte array to string
   *
   * @param data byte array data.
   * @return string.
   */
  public static String encodeString(byte[] data) {
    return encodeString(data, " ", true);
  }

  /**
   * convert byte array to string with every 2 char with split
   *
   * @param data byte array data.
   * @param split string object split.
   * @param toLowerCase true is lower case, false is upper case.
   * @return string.
   */
  public static String encodeString(byte[] data, String split, boolean toLowerCase) {
    return StringUtil.convertToString(new String(encode(data, toLowerCase)), 2, split);
  }

  /**
   * convert byte array to hex char array
   *
   * @param data byte array data.
   * @return hex char array.
   */
  public static char[] encode(byte[] data) {
    return encode(data, true);
  }

  /**
   * convert byte array to hex char array
   *
   * @param data byte array data.
   * @param toLowerCase true is lowercase, false is uppercase.
   * @return hex char array.
   */
  public static char[] encode(byte[] data, boolean toLowerCase) {
    return encode0(data, toLowerCase? HEXADECIMAL: HEXADECIMAL_UPPER);
  }

  private static char[] encode0(byte[] data, char[] hexChar) {
    char[] hex = new char[data.length * 2];
    for (int i = 0, j = 0; i < data.length; i++) {
      byte b = data[i];
      hex[j++] = hexChar[(0xF0 & b) >> 4];
      hex[j++] = hexChar[0x0F & b];
    }
    return hex;
  }

  /**
   * convert hex string with whitespace split to byte array
   *
   * @param data hex string.
   * @return byte array.
   * @throws IllegalArgumentException data include invalid character.
   * @throws NullPointerException when data or separator is {@code null}.
   */
  public static byte[] decodeString(String data)
      throws IllegalArgumentException, NullPointerException {
    return decode(data, " ");
  }

  /**
   * convert hex string with split to byte array
   *
   * @param data hex string.
   * @param split split.
   * @return byte array.
   * @throws IllegalArgumentException data include invalid character.
   * @throws NullPointerException when data or separator is {@code null}.
   */
  public static byte[] decode(String data, String split)
      throws IllegalArgumentException, NullPointerException {
    return decode(StringUtil.convertToCharArray(data, split));
  }

  /**
   * convert hex char array to byte array
   *
   * @param data hex char array.
   * @return byte array.
   * @throws IllegalArgumentException data include invalid character.
   * @throws NullPointerException data is null or empty.
   */
  public static byte[] decode(char[] data) throws IllegalArgumentException, NullPointerException {
    if (null == data || data.length == 0) {
      throw new NullPointerException();
    }
    return decode0(data);
  }

  private static byte[] decode0(char[] data) {
    byte[] hex = new byte[data.length / 2];
    for (int i = 0, j = 0; i < hex.length; i++, j = j + 2) {
      int f = toDigit(data[j]) << 4;
      f |= toDigit(data[j + 1]);
      hex[i] = (byte) (f & 0xFF);
    }
    return hex;
  }

  /**
   * Return the numeric value of the hexadecimal character.
   *
   * @param hexChar the character to be converted.
   * @return the numeric value represented by the hexadecimal character.
   * @throws IllegalArgumentException the numeric is not hexadecimal character.
   */
  private static int toDigit(char hexChar) throws IllegalArgumentException {
    int digit = HEXADECIMAL_DECODE_TABLE[hexChar];
    if (digit < 0) {
      throw new IllegalArgumentException("Invalid Hexadecimal Character: " + hexChar);
    }
    return digit;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy