13

I know that you can use printf and also use StringBuilder.append(String.format("%x", byte)) to convert values to HEX values and display them on the console. But I want to be able to actually format the byte array so that each byte is displayed as HEX instead of decimal.

Here is a section of my code that I have already that does the first two ways that I stated:

if(bytes > 0)
    {
        byteArray = new byte[bytes]; // Set up array to receive these values.

        for(int i=0; i<bytes; i++)
        {
            byteString = hexSubString(hexString, offSet, CHARSPERBYTE, false); // Isolate digits for a single byte.
            Log.d("HEXSTRING", byteString);

            if(byteString.length() > 0)
            {
                byteArray[i] = (byte)Integer.parseInt(byteString, 16); // Parse value into binary data array.
            }
            else
            {
                System.out.println("String is empty!");
            }

            offSet += CHARSPERBYTE; // Set up for next word hex.    
        }

        StringBuilder sb = new StringBuilder();
        for(byte b : byteArray)
        {
            sb.append(String.format("%x", b));
        }

        byte subSystem = byteArray[0];
        byte highLevel = byteArray[1];
        byte lowLevel = byteArray[2];

        System.out.println("Byte array size: " + byteArray.length);
        System.out.printf("Byte 1: " + "%x", subSystem);
        System.out.printf("Byte 2: " + "%x", highLevel);
        System.out.println("Byte 3: " + lowLevel);
        System.out.println("Byte array value: " + Arrays.toString(byteArray));
        System.out.println("Byte array values as HEX: " + sb.toString());
    }
    else
    {
        byteArray = new byte[0]; // No hex data.

        //throw new HexException();
    }

    return byteArray;

The string that was split up into the byte array was:

"1E2021345A2B"

But displays it as decimal on the console as:

"303233529043"

Could anyone please help me on how to get the actual values to be in hex and be displayed in that way naturally. Thank you in advance.

user987339
  • 10,519
  • 8
  • 40
  • 45
James Meade
  • 1,147
  • 5
  • 22
  • 46

4 Answers4

31

You can use the String javax.xml.bind.DatatypeConverter.printHexBinary(byte[]). e.g.:

public static void main(String[] args) {
    byte[] array = new byte[] { 127, 15, 0 };
    String hex = DatatypeConverter.printHexBinary(array);
    System.out.println(hex); // prints "7F0F00"
}
Paul Vargas
  • 41,222
  • 15
  • 102
  • 148
26

String.format actually makes use of the java.util.Formatter class. Instead of using the String.format convenience method, use a Formatter directly:

Formatter formatter = new Formatter();
for (byte b : bytes) {
    formatter.format("%02x", b);
}
String hex = formatter.toString();

As of Java 17, HexFormat can do this in one line:

String hex = HexFormat.of().formatHex(bytes);
VGR
  • 40,506
  • 4
  • 48
  • 63
  • 1
    This is the shortest, simplest answer to this question I've been able to find which does not rely on non-standard libraries. Very excellent!!! – Ethan Dec 10 '15 at 05:34
  • Cleanest solution by far. Thank you! Worth mentioning that you can put `x` in uppercase and add a white space after it in the upper case to make it look more readable – Victor Queiroz Oct 07 '18 at 00:58
  • Does this pad a zero if the last byte is less than 16? – Constance Eustace Nov 18 '21 at 16:40
  • @ConstanceEustace The `0` in `%02x` means ‘pad with zero if necessary to guarantee there are two digits.’ From [the documentation](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Formatter.html#dnint): “If the '0' flag is given then the output will be padded to the field width with leading zeros after the radix indicator or sign (if present).” – VGR Nov 18 '21 at 18:08
6

The way I do it:

  private static final char[] HEX_CHARS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A',
      'B', 'C', 'D', 'E', 'F' };

  public static String toHexString(byte[] bytes) {
    char[] hexChars = new char[bytes.length * 2];
    int v;
    for (int j = 0; j < bytes.length; j++) {
      v = bytes[j] & 0xFF;
      hexChars[j * 2] = HEX_CHARS[v >>> 4];
      hexChars[j * 2 + 1] = HEX_CHARS[v & 0x0F];
    }
    return new String(hexChars);
  }
Tamas
  • 3,254
  • 4
  • 29
  • 51
  • I still want to return a byte array though where each byte has been formatted to hex. e.g. the string was 1E and the byte is now 30 in decimal and I want the byte to be formatted back to 1E. Is there a way of doing this? – James Meade Oct 18 '13 at 13:10
  • It requires two HEX characters to 'describe' 1 byte. You can represent 1 hex characters using 1 byte, if you encode the hex char using the hex chrar's ASCII code. Hence, you need two bytes to describe one byte in hex, in ASCII. I'm not sure what you really want. – Tamas Oct 18 '13 at 13:15
  • I want to have two characters occupying 1 single byte. So for my example, I have a byte array of 6. – James Meade Oct 18 '13 at 13:24
  • You should learn about bytes, numeral systems, characters and their encoding in bits, called 'character encoding'. By default, an ascii character is encoded using 1 byte (8 bits). Hexadecimal is a numeral system where each number can span from 0-F. This number can be represented by an ascii character. You need two hex numbers to describe a byte (8 bits). If you want to display these two numbers using ascii characters, then you need two characters and thus two bytes. – Tamas Oct 18 '13 at 13:27
  • I want to use a hex number as a representation. Not a hex character from ascii, so I just want it as 1E instead of 0x31 and 0x45. – James Meade Oct 18 '13 at 13:34
  • 0x31 and 0x45 are already hex numbers, their 'hex' representation is not 1E, but actually "31" and "45". – Tamas Oct 18 '13 at 13:38
  • I know that they are hex numbers, but what is the hex value of 1E called when the hex numbers are 31 and 45. 1 = 31, E = 45. – James Meade Oct 18 '13 at 13:45
  • The 'The hex value of "1E"' is doesn't make sense just like the 'binary value of 010010110' or the decimal value of '9234' doesn't make sense. The decimal value of hex number '1E' is 30. The hex value of the deciaml value '30' is 1E. – Tamas Oct 18 '13 at 13:48
  • 1
    And this that is exactly about conversion between numeral systems: http://www.youtube.com/watch?v=Fpm-E5v6ddc – Tamas Oct 18 '13 at 14:08
  • Those videos were very helpful and I understand it better now thank you. – James Meade Oct 18 '13 at 14:45
2

Try this

byte[] raw = some_bytes;
javax.xml.bind.DatatypeConverter.printHexBinary(raw)
Dharmesh Gohil
  • 324
  • 2
  • 6