To convert a byte array to a hexadecimal (hex) string in Java, you can use several methods depending on your needs for efficiency, readability, or Java version. Below are detailed approaches with examples:
1. Lookup Table Method (Efficient)
This method uses a pre-defined lookup table for fast conversion, avoiding expensive string operations.
public class HexConverter {
private static final char[] HEX_ARRAY = "0123456789abcdef".toCharArray();
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for (int i = 0; i < bytes.length; i++) {
int value = bytes[i] & 0xFF; // Convert to unsigned integer (0-255)
hexChars[i * 2] = HEX_ARRAY[value >>> 4]; // High nibble
hexChars[i * 2 + 1] = HEX_ARRAY[value & 0x0F]; // Low nibble
}
return new String(hexChars);
}
public static void main(String[] args) {
byte[] bytes = {0x12, 0x34, (byte) 0xAB, (byte) 0xFF};
String hexString = bytesToHex(bytes);
System.out.println(hexString); // Output: 1234abff
}
}
Key Points:
- Efficiency: Direct array indexing for O(n) time complexity.
- Case Handling: Use
HEX_ARRAY = "0123456789ABCDEF".toCharArray()
for uppercase. - Edge Cases: Handles empty arrays and negative byte values correctly.
2. String.format
with StringBuilder
(Readable)
Leverages String.format
for simplicity, but less efficient due to repeated string operations.
public class HexConverter {
public static String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b & 0xFF)); // Lowercase
// For uppercase: use "%02X"
}
return sb.toString();
}
public static void main(String[] args) {
byte[] bytes = {0x12, 0x34, (byte) 0xAB};
System.out.println(bytesToHex(bytes)); // Output: 1234ab
}
}
Key Points:
- Readability: Easy to understand but slower for large arrays.
- Format Specifier:
%02x
ensures two-character padding (e.g.,0a
instead ofa
).
3. Java 17+ HexFormat
(Modern Approach)
Java 17 introduced java.util.HexFormat
for streamlined conversions.
import java.util.HexFormat;
public class HexConverter {
public static void main(String[] args) {
byte[] bytes = {0x12, 0x34, (byte) 0xAB};
HexFormat hexFormat = HexFormat.of();
String hexString = hexFormat.formatHex(bytes);
System.out.println(hexString); // Output: 1234ab
}
}
Key Points:
- Simplicity: Built-in class handles formatting.
- Case Control: Use
HexFormat.of().withUpperCase()
for uppercase. - Delimiters: Supports adding delimiters between bytes (e.g.,
formatHex(bytes, " ")
).
Comparison of Methods
Method | Pros | Cons |
---|---|---|
Lookup Table | Fastest, no dependencies | More code to write |
String.format | Simple, readable | Slower for large arrays |
HexFormat (Java 17) | Modern, concise | Requires Java 17+ |
Examples & Edge Cases
Example 1: Basic Conversion
byte[] bytes = {0x0A, 0x1B, (byte) 0xFF};
System.out.println(bytesToHex(bytes)); // Output: 0a1bff
Example 2: Empty Array
byte[] emptyBytes = {};
System.out.println(bytesToHex(emptyBytes)); // Output: (empty string)
Example 3: Negative Byte
byte negativeByte = (byte) 0x8F; // Interpreted as -113 in Java
System.out.println(bytesToHex(new byte[]{negativeByte})); // Output: 8f
Handling Uppercase
- Lookup Table: Change
HEX_ARRAY
to uppercase characters. - String.format: Use
%02X
instead of%02x
. - HexFormat: Use
HexFormat.of().withUpperCase()
.
Summary
- For Efficiency: Use the lookup table method.
- For Readability: Use
String.format
withStringBuilder
. - For Modern Codebases: Use
HexFormat
(Java 17+). - Always handle byte-to-integer conversion with
& 0xFF
to avoid sign extension issues.