Question
How can you convert a byte array to a hexadecimal string and then convert a hexadecimal string back into a byte array in Java?
Short Answer
By the end of this page, you will understand how hexadecimal encoding works, how to convert byte[] to a hex string, how to parse a hex string back into bytes, and what common mistakes to avoid when working with binary data in Java.
Concept
Hexadecimal is a base-16 number system that represents binary data in a human-readable form. Each hexadecimal character represents 4 bits, so one byte, which has 8 bits, is represented by exactly 2 hex characters.
In Java, a byte[] stores raw binary data. This is useful for files, hashes, encryption keys, network packets, and image data. But raw bytes are not easy for humans to read or print. That is where hex strings help.
For example, this byte array:
byte[] data = { 15, 42 };
can be represented as:
0f2a
This matters in real programming because many systems display binary values as hex:
- MD5, SHA-256, and other hash outputs
- Token and key debugging
- File signatures
- Network protocol inspection
- Logging raw binary values safely
The reverse conversion is also common. If a program receives a hex string such as ff0a10, it may need to turn it back into real bytes for further processing.
A key rule to remember is:
- 1 byte = 2 hex characters
So any valid hex string for conversion back to bytes must have an even number of characters.
Mental Model
Think of a byte array as a box of raw machine values, and a hex string as a label printed in a format humans can read.
- The
byte[]is the real data. - The hex string is a readable representation of that data.
It is similar to writing a street address on paper instead of describing a location using map coordinates in binary.
Another simple way to think about it:
- A byte is one full item.
- Hex splits that item into two visible symbols.
- So every byte becomes two hex digits.
If you see the hex string 4f, that is one byte.
If you see 4f2a, that is two bytes.
Syntax and Examples
Convert byte[] to hex string
A common approach is to loop through each byte and format it as two hexadecimal characters.
public static String bytesToHex(byte[] bytes) {
StringBuilder hex = new StringBuilder();
for (byte b : bytes) {
hex.append(String.format("%02x", b));
}
return hex.toString();
}
Example
byte[] data = { 10, 15, 31 };
String hex = bytesToHex(data);
System.out.println(hex);
Output:
0a0f1f
%02x means:
%x= format as hexadecimal2= use at least 2 characters0= pad with leading zero if needed
Step by Step Execution
Consider this code:
byte[] data = { 10, 15 };
String hex = bytesToHex(data);
Using this method:
public static String bytesToHex(byte[] bytes) {
StringBuilder hex = new StringBuilder();
for (byte b : bytes) {
hex.append(String.format("%02x", b));
}
return hex.toString();
}
Step by step
datacontains two bytes:10and15- A new empty
StringBuilderis created - The loop reads the first byte:
10 String.format("%02x", 10)becomes0a0ais appended to the builder
Real World Use Cases
Hex conversion appears in many everyday programming tasks.
1. Displaying hash values
Hash algorithms return raw bytes, but developers usually print them as hex.
byte[] hash = messageDigest.digest(data);
String hexHash = bytesToHex(hash);
2. Logging binary data
When debugging file content, network packets, or cryptographic values, hex is easier to inspect than raw bytes.
3. Reading configuration values
Some systems store IDs, colors, keys, or binary tokens as hex strings in configuration files or environment variables.
4. Working with file signatures
Many file formats begin with fixed byte patterns. Hex makes those patterns readable.
Example:
- PNG starts with bytes shown as
89504e47
5. Interfacing with APIs and protocols
Some APIs send binary payloads as hexadecimal text, especially in lower-level systems or device communication.
Real Codebase Usage
In real Java projects, byte-to-hex conversion is usually wrapped in utility methods so the logic stays reusable and consistent.
Common patterns
Utility helper methods
Developers often create a small utility class:
public final class HexUtils {
private HexUtils() {}
public static String bytesToHex(byte[] bytes) {
StringBuilder hex = new StringBuilder();
for (byte b : bytes) {
hex.append(String.format("%02x", b));
}
return hex.toString();
}
}
Validation before parsing
When converting from text to bytes, code often checks:
- string is not
null - length is even
- characters are valid hex digits
Error handling
If input comes from users or external systems, parsing can fail. Real code often throws a clear exception or returns a validation error.
Normalization
Many codebases normalize hex to lowercase or uppercase so logs and comparisons are consistent.
Common Mistakes
1. Forgetting that one byte needs two hex characters
Broken idea:
byte[] bytes = new byte[hex.length()];
Why it is wrong:
- Two hex characters represent one byte
- The correct array length is
hex.length() / 2
2. Not checking for odd-length hex strings
Broken code:
String hex = "abc";
byte[] bytes = hexToBytes(hex);
Why it is wrong:
abchas 3 characters- You cannot split it into full byte pairs
Fix:
if (hex.length() % 2 != 0) {
throw new IllegalArgumentException("Hex string must have an even length");
}
3. Using toString() on a byte array
Broken code:
Comparisons
| Concept | Purpose | Example | Notes |
|---|---|---|---|
byte[] | Stores raw binary data | {10, 15} | Actual data used by the program |
| Hex string | Human-readable form of bytes | 0a0f | 2 hex characters per byte |
| Base64 string | Compact text encoding for binary | Cg8= | Shorter than hex, often used in APIs |
| Decimal output | Numeric display of values | 10 15 | Readable, but not standard for binary protocols |
Hex vs Base64
Cheat Sheet
Byte array to hex
public static String bytesToHex(byte[] bytes) {
StringBuilder hex = new StringBuilder();
for (byte b : bytes) {
hex.append(String.format("%02x", b));
}
return hex.toString();
}
Hex to byte array
public static byte[] hexToBytes(String hex) {
if (hex.length() % 2 != 0) {
throw new IllegalArgumentException("Hex string must have an even length");
}
byte[] bytes = new byte[hex.length() / 2];
for (int i = 0; i < hex.length(); i += 2) {
bytes[i / 2] = (byte) Integer.parseInt(hex.substring(i, i + 2), 16);
}
bytes;
}
FAQ
How do I convert bytes to a hex string in Java?
Loop through the byte array and format each byte as a two-character hexadecimal value using String.format("%02x", b).
How do I convert a hex string back to a byte array?
Read the string two characters at a time, parse each pair with base 16, and store the result in a byte[].
Why does each byte need two hex characters?
Because one hex character represents 4 bits, and one byte contains 8 bits.
Can a hex string use uppercase letters?
Yes. Both uppercase (A-F) and lowercase (a-f) are valid hex digits.
Why do some bytes print as negative numbers in Java?
Java byte values are signed, ranging from -128 to 127. The underlying binary data is still correct.
What happens if the hex string has an odd length?
It is invalid for byte conversion because bytes must be represented by pairs of hex characters.
Is hex the same as Base64?
No. Both represent binary data as text, but hex is more readable while Base64 is more compact.
Mini Project
Description
Build a small Java utility that converts data between byte arrays and hexadecimal strings. This demonstrates both directions of conversion and adds input validation, which is common in real applications that handle hashes, file signatures, or encoded binary values.
Goal
Create a program that prints a byte array as a hex string, then converts that hex string back into the original byte array.
Requirements
- Create a method that converts a
byte[]to a hex string. - Create a method that converts a hex string to a
byte[]. - Reject hex strings with an odd number of characters.
- In
main, test both methods with sample data. - Print the original bytes, the hex string, and the restored bytes.
Keep learning
Related questions
AddTransient vs AddScoped vs AddSingleton in ASP.NET Core Dependency Injection
Learn the differences between AddTransient, AddScoped, and AddSingleton in ASP.NET Core DI with examples and practical usage.
C# Type Checking Explained: typeof vs GetType() vs is
Learn when to use typeof, GetType(), and is in C#. Understand exact type checks, inheritance, and safe type testing clearly.
C# Version Numbers Explained: C# vs .NET Framework and Why “C# 3.5” Is Incorrect
Learn the correct C# version numbers, how they map to .NET releases, and why terms like C# 3.5 are inaccurate and confusing.