When you inspect binary data, a hexadecimal string can be easier to read than a list of decimal byte values. You might use it when troubleshooting a file format or checking a message exchanged between applications.
This tutorial shows a complete conversion in both directions, including readable formatting and invalid input handling.
1. Choose a hexadecimal format
Java 17 introduced java.util.HexFormat as a standard API. No preview or incubator flags are needed.
Use HexFormat.of() for lowercase output without separators. For uppercase output with colons between bytes, use:
HexFormat readable =
HexFormat.ofDelimiter(":").withUpperCase();
Each byte becomes two hexadecimal digits. These options are documented in the Java 17 HexFormat API.
2. Create the complete example
Save the following as HexFormatExample.java:
import java.util.Arrays;
import java.util.HexFormat;
public class HexFormatExample {
public static void main(String[] args) {
byte[] packet = {
0, 15, 16, 127, (byte) 128, (byte) 255
};
HexFormat plain = HexFormat.of();
HexFormat readable =
HexFormat.ofDelimiter(":").withUpperCase();
System.out.println(
"Compact: " + plain.formatHex(packet));
String formatted = readable.formatHex(packet);
System.out.println("Readable: " + formatted);
byte[] restored = readable.parseHex(formatted);
System.out.println(
"Same bytes: " + Arrays.equals(packet, restored));
System.out.println(
"Java bytes: " + Arrays.toString(restored));
try {
readable.parseHex("00:GG");
} catch (IllegalArgumentException exception) {
System.out.println(
"Invalid input: expected hexadecimal byte pairs");
}
}
}
The program first creates sample data. It then prints two representations, parses the colon-separated version, and checks whether the recovered bytes match the original.
3. Compile and run
Open a terminal in the directory containing the file:
javac --release 17 HexFormatExample.java
java HexFormatExample
Output:
Compact: 000f107f80ff
Readable: 00:0F:10:7F:80:FF
Same bytes: true
Java bytes: [0, 15, 16, 127, -128, -1]
Invalid input: expected hexadecimal byte pairs
4. Understand the result
The two formatted strings represent identical data. Java’s signed byte representation explains the negative decimal values in the recovered array: the bit patterns 80 and FF correspond to -128 and -1.
Arrays.equals() confirms that the conversion preserved the bytes.
Parsing must use the expected delimiters. Invalid digits, such as GG, cause IllegalArgumentException; hexadecimal digit letters themselves are case-insensitive. See HexFormat.parseHex().
Best practices
- Define the expected representation when exchanging data with another application.
- Use a matching formatter for encoding and decoding.
- Keep the original bytes when your next operation requires binary data.
- Handle invalid external input at the point where it enters your application.
- Remember that hexadecimal encoding makes data readable; it does not encrypt it.
Summary
Use formatHex() to turn bytes into hexadecimal text and parseHex() to recover them. A short round-trip example helps verify your chosen representation before integrating it into a larger application.
