In Java, How to Convert a Byte Array to a String of Hex Digits While Keeping Leading Zeros

In Java, how do I convert a byte array to a string of hex digits while keeping leading zeros?

A simple approach would be to check how many digits are output by Integer.toHexString() and add a leading zero to each byte if needed. Something like this:

public static String toHexString(byte[] bytes) {
StringBuilder hexString = new StringBuilder();

for (int i = 0; i < bytes.length; i++) {
String hex = Integer.toHexString(0xFF & bytes[i]);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}

return hexString.toString();
}

How to convert a byte array to a hex string in Java?

From the discussion here, and especially this answer, this is the function I currently use:

private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
}
return new String(hexChars);
}

My own tiny benchmarks (a million bytes a thousand times, 256 bytes 10 million times) showed it to be much faster than any other alternative, about half the time on long arrays. Compared to the answer I took it from, switching to bitwise ops --- as suggested in the discussion --- cut about 20% off of the time for long arrays. (Edit: When I say it's faster than the alternatives, I mean the alternative code offered in the discussions. Performance is equivalent to Commons Codec, which uses very similar code.)

2k20 version, with respect to Java 9 compact strings:

private static final byte[] HEX_ARRAY = "0123456789ABCDEF".getBytes(StandardCharsets.US_ASCII);
public static String bytesToHex(byte[] bytes) {
byte[] hexChars = new byte[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
}
return new String(hexChars, StandardCharsets.UTF_8);
}

How to convert a byte array to a hex string in Java?

From the discussion here, and especially this answer, this is the function I currently use:

private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
}
return new String(hexChars);
}

My own tiny benchmarks (a million bytes a thousand times, 256 bytes 10 million times) showed it to be much faster than any other alternative, about half the time on long arrays. Compared to the answer I took it from, switching to bitwise ops --- as suggested in the discussion --- cut about 20% off of the time for long arrays. (Edit: When I say it's faster than the alternatives, I mean the alternative code offered in the discussions. Performance is equivalent to Commons Codec, which uses very similar code.)

2k20 version, with respect to Java 9 compact strings:

private static final byte[] HEX_ARRAY = "0123456789ABCDEF".getBytes(StandardCharsets.US_ASCII);
public static String bytesToHex(byte[] bytes) {
byte[] hexChars = new byte[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
}
return new String(hexChars, StandardCharsets.UTF_8);
}

Convert a string representation of a hex dump to a byte array using Java?

Update (2021) - Java 17 now includes java.util.HexFormat (only took 25 years):

HexFormat.of().parseHex(s)


For older versions of Java:

Here's a solution that I think is better than any posted so far:

/* s must be an even-length string. */
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}

Reasons why it is an improvement:

  • Safe with leading zeros (unlike BigInteger) and with negative byte values (unlike Byte.parseByte)

  • Doesn't convert the String into a char[], or create StringBuilder and String objects for every single byte.

  • No library dependencies that may not be available

Feel free to add argument checking via assert or exceptions if the argument is not known to be safe.

How to convert an int to hex with leading zeros in Java?

String hexAddress = String.format("%1$02X",address);

%1 means these flags are for the first argument. In this case, there is only one argument.

$ separates the argument index from the flags

0 is a flag that means pad the result with leading zeros up to the specified bit width.

2 is the bit width

X means convert the number to hex, and use uppercase letters. x would convert to hex and use lowercase letters.

You can read more about the different possible arguments by examining the Java Formatter class.

Converting hex to binary with leading zeros

You can pad with spaces using String.format("%64s") and then replace spaces with zeros. This has the advantage of working for any size of input, not just something in the int range. I'm guessing you're working with arbitrary inputs from your use of BigInteger...

String value = new BigInteger("3031323334353637", 16).toString(2);
System.out.println(String.format("%64s", value).replace(" ", "0"));

Output

0011000000110001001100100011001100110100001101010011011000110111

Explanation... The String.format("%64s, value) outputs the earlier String padded to fill 64 characters.

"  11000000110001001100100011001100110100001101010011011000110111"

The leading spaces are then replaced with '0' characters using String.replace(oldString, newString)

"0011000000110001001100100011001100110100001101010011011000110111"

Pad a binary String equal to zero (0) with leading zeros in Java

For padding with, say, 5 leading zeroes, this will work:

String.format("%5s", Integer.toBinaryString(data)).replace(' ', '0');

You didn't specify the expected length of the string, in the sample code above I used 5, replace it with the proper value.

EDIT

I just noticed the comments. Sure you can build the pattern dynamically, but at some point you have to know the maximum expected size, depending on your problem, you'll know how to determine the value:

String formatPattern = "%" + maximumExpectedSize + "s";


Related Topics



Leave a reply



Submit