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
Convert hex string to byte[]
To convert back, read the string two characters at a time, parse each pair as a base-16 number, and store it as a byte.
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) {
String hexPair = hex.substring(i, i + 2);
bytes[i / 2] = (byte) Integer.parseInt(hexPair, 16);
}
return bytes;
}
Example
String hex = "0a0f1f";
byte[] data = hexToBytes(hex);
for (byte b : data) {
System.out.println(b);
}
Output:
10
15
31
Full example
public class HexExample {
public static String bytesToHex(byte[] bytes) {
StringBuilder hex = new StringBuilder();
for (byte b : bytes) {
hex.append(String.format("%02x", b));
}
return hex.toString();
}
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) {
String hexPair = hex.substring(i, i + 2);
bytes[i / 2] = (byte) Integer.parseInt(hexPair, 16);
}
return bytes;
}
public static void main(String[] args) {
byte[] original = { 72, 101, 120 };
String hex = bytesToHex(original);
System.out.println("Hex: " + hex);
byte[] restored = hexToBytes(hex);
System.out.print("Bytes: ");
for (byte b : restored) {
System.out.print(b + " ");
}
}
}
This converts bytes to hex, then converts the hex back to the original bytes.
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- The loop reads the second byte:
15 String.format("%02x", 15)becomes0f0fis appended- The final string is
0a0f
Now converting back:
byte[] result = hexToBytes("0a0f");
Using this method:
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) {
String hexPair = hex.substring(i, i + 2);
bytes[i / 2] = (byte) Integer.parseInt(hexPair, 16);
}
return bytes;
}
Step by step
- The string is
0a0f - Its length is 4, which is valid because it is even
- A byte array of size
2is created - The loop starts at
i = 0 substring(0, 2)gives0aInteger.parseInt("0a", 16)becomes10- That value is stored in
bytes[0] - The loop moves to
i = 2 substring(2, 4)gives0fInteger.parseInt("0f", 16)becomes15- That value is stored in
bytes[1] - The final byte array is
{10, 15}
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.
Guard clauses
A common style is to reject bad input early:
if (hex == null || hex.length() % 2 != 0) {
throw new IllegalArgumentException("Invalid hex string");
}
This keeps the main conversion logic simpler.
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:
byte[] data = {10, 15};
System.out.println(data.toString());
Output will look like this:
[B@1a2b3c4d
Why it is wrong:
toString()on an array does not print its contents- Use a conversion method or
Arrays.toString(data)for numeric output
4. Ignoring signed bytes in Java
Java bytes are signed, from -128 to 127. That can confuse beginners.
Example:
byte b = (byte) 255;
System.out.println(b); // prints -1
This does not mean the hex conversion is wrong. It is just how Java stores bytes.
5. Not validating invalid characters
Broken input:
String hex = "0g";
Why it is wrong:
gis not a valid hexadecimal digit- Valid hex digits are
0-9,a-f, andA-F
6. Assuming hex is the same as text encoding
Hex is not the same as UTF-8 or ASCII. It is just a textual representation of raw bytes.
For example:
- text:
Hi - bytes in UTF-8:
72 105 - hex representation:
4869
These are related, but not the same thing.
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
| Feature | Hex | Base64 |
|---|---|---|
| Readability | Very easy to inspect byte-by-byte | Less intuitive for manual inspection |
| Size | Larger output | Smaller output |
| Common use | Debugging, hashes, low-level data | APIs, file transfer, tokens |
| Mapping | 2 characters per byte | About 4 characters per 3 bytes |
Manual conversion vs library methods
| Approach | Pros | Cons |
|---|---|---|
| Manual loop | Easy to learn and control | More code to maintain |
| Utility/library method | Cleaner in production | You need to know the API |
For learning, manual conversion is excellent because it shows exactly how hex encoding works.
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);
}
return bytes;
}
Key rules
1 byte = 2 hex characters- Valid hex digits:
0-9,a-f,A-F - Hex string length must be even
- Java
byteis signed, but hex still represents the correct underlying bits
Quick examples
bytesToHex(new byte[] {10, 15}); // "0a0f"
hexToBytes("0a0f"); // {10, 15}
Watch out for
- Odd-length strings
- Invalid characters like
gorz - Confusing text encoding with hex encoding
- Using
toString()on arrays
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.
Best Way to Repeat a Character in C#: Building Repeated Strings Efficiently
Learn the best way to repeat a character in C#, compare StringBuilder, string concatenation, and simpler built-in options.
C# Access Modifiers and static: public, private, protected, and Defaults
Learn how C# public, private, protected, and default access control visibility, and how static differs from instance members.