Explain Codes LogoExplain Codes Logo

How can I convert a byte array to hexadecimal in Java?

java
prompt-engineering
performance
best-practices
Alex KataevbyAlex Kataev·Sep 21, 2024
TLDR

Need a quick, no-fuss solution? Here's a compact piece of code that does exactly what you need:

byte[] byteArray = {10, 2, 15, 11}; StringBuilder hexString = new StringBuilder(); for (byte b : byteArray) { hexString.append(String.format("%02X", b)); } System.out.println(hexString); // Who knew bytes could look so pretty: "0A020F0B"

We're utilizing the "%02X" format with String.format to get a zero-padded, 2-digit hexadecimal representation per byte.

Unleashing the underdog: negative bytes

Surprisingly, bytes are a little bipolar. They can be positive or negative. When this happens during the conversion, you might see some surprising results due to sign extension. Here's a rescue plan using a bitwise AND with 0xFF to keep things positive:

String hex = String.format("%02X", b & 0xFF); // Stay positive byte, stay positive

This preserves our dear leading zeroes that could get lost in translation.

Tune-up for performance seekers

For the need for speed, String.format might fall short with larger arrays. Enter the speed demon, bitwise operations and predefined hex char array:

// Speed, I am speed - Lightning McByte char[] hexArray = "0123456789ABCDEF".toCharArray(); StringBuilder hexBuilder = new StringBuilder(byteArray.length * 2); for (byte b : byteArray) { hexBuilder.append(hexArray[(b >>> 4) & 0x0F]); hexBuilder.append(hexArray[b & 0x0F]); }

This twist is a leap in performance for large arrays.

Stellar point: understanding conversion

During each byte conversion, we're doing a widening primitive conversion. Here's the gist: bytes are signed in Java - they can play negative. If we don't mask, sign extension may lead to bogus hex representation.

Guide to explore java.util.Formatter

The java.util.Formatter is packed with advanced formatting controls. Mastering Formatter syntax is like unlocking the next level in Java formatting.

Huge byte arrays? BigInteger to the rescue

Dealing with massive arrays or negative bytes like a boss using java.math.BigInteger. It takes a signum and a byte array and does an outstandingly accurate hexadecimal conversion:

// When the bytes go big, BigInteger goes home with the trophy String hex = new BigInteger(1, byteArray).toString(16); // Big (Integer) things are happening

This technique shines with negative bytes but beware, it will strip leading zeros. You might need to add them back manually.

Speed racer's corner: faster alternatives

Swiftly navigating with lookup tables

A lookup table with predefined hex characters could be your secret weapon. It's like turbocharging the conversion process. We already discussed the array-based method, which is a incarnation of this.

The conundrum: String.format vs bitwise operations

A classic readability vs speed debate. The String.format method is easier to read and understand; however, bitwise operations are faster. It's a trade-off and you need to pick according to your requirements.

When Integer.toHexString disappoints

Another tool you have is Integer.toHexString, but it's not very gracious with negative numbers. Use it, but be prepared for occasional frustrations.

Java versions and conversion methods: A cautionary tale

Ensure that your chosen method runs smoothly on different Java versions. Methods can behave differently or be deprecated in newer releases making your code a tad bit incompatible.