Tuesday, May 9, 2023

How to Convert and Print Byte array to Hex String in Java? Example

We often need to convert byte arrays to Hex String in Java, In order to print byte array contents in a readable format. Since many cryptographic algorithms e.g. MD5 return the hash value as a byte array, In order to see and compare that byte array, you need to convert the byte array to Hex String. As we have seen, while generating MD5 checksum of File, there are multiple ways to convert byte array to Hexadecimal String in Java. You can either write your own method, or you can use an open-source library e.g. Apache commons-codec to create Hex String from a byte array in Java. Commons codec provides a utility class Hex, which contains an encodeHexString() method to create Hex String from a byte array.

It's one of the best options to generate Hex String if you are already using this library to generate MD5 hash values. In this Java tutorial, we will see what is the issue with printing byte array as normal String, and 2 examples to convert a byte array into Hexadecimal String in Java.


The issue with Printing Byte arrays as String

How to convert and Print byte array to Hex String in Java with ExampleSome of you might be wondering, why can't we use String constructor which accepts byte array e.g. new String(byte[]). Well, the real issue with printing byte array is non-printable ASCII characters.  Your MD5 checksum or any byte array may contain some non-printable characters, which means you can not compare two-byte arrays by looking at their String representation. 



By the way, this is not a problem if you are encoding String in base64, as they only use printable ASCII characters. In our code example of printing byte array as normal String, you can see different strings, generated from different byte arrays, looks the same. 

Since 0, 5 and 6 represent non-printable characters ASCII characters NUL, ENQ and ACK, they are showing here as white space here. This issue can be resolved if we convert byte array to Hexadecimal String, and then print or display it.

Benefits of Printing Byte array as Hex String in Java

There are a couple of benefits of printing byte array as Hex String in Java. In fact, displaying byte array as Hex String is normal practice, especially when you want to see and compare MD5 hash or digest value, generated by the cryptographic algorithm.

1) It's easy to display contents of byte array in a standard way, as byte array may contain non-printable characters.
2) Hex String allows you to quickly compare two-byte arrays contents.
3) Hex String is easy to read, compared to binary or decimal format as it takes fewer digits.

These are some notable benefits of printing byte array as a hex string in Java.


2 ways to Convert Byte Array to Hex String in Java

As I said, there are multiple ways to generate hexadecimal String from byte array in Java e.g. including symbol array, and using the String format method. In this Java program, we will see two examples to convert byte array to Hexadecimal String. 

In the first example, we have used core Java, and in the second example, we have used Apache commons-codec library. It provides a utility class org.apache.commons.codec.binary.Hex, which can convert byte array to Hex String in Just one line

I am big fan of using open source libraries, especially for production usage. By the way, we will also look issue with printing byte array as normal String, which may help you to understand need of converting byte array to Hex String before printing them.

import java.util.logging.Logger;
import org.apache.commons.codec.binary.Hex;

/**
 * Java program to convert Byte array to Hex String in Java.
 * This Java example uses core Java and Apache commons code to
 * generate Hexadecimal String from byte array in Java.
 *
 * @author Javin Paul
 */
public class ByteArrayToHexString {
    private static final Logger logger = Logger.getLogger(StringReplace.class.getName());
    
    public static void main(String args[]) {
       
       //byte array with non printable characters 
       byte[] bytes = new byte[]{'a', 'b', 0, 5, 'c','d'};
       byte[] nonprintable = new byte[]{'a', 'b', 0, 6, 'c','d'};
     
       //You can not print byte array as String because they may contain non printable
       //characters e.g. 0 is NUL, 5 is ENQ and 6 is ACK in ASCII format
      
       String value = new String(bytes);
       System.out.println(value);      
       String str = new String(nonprintable);
       System.out.println(str);   
      
       //Converting byte array to Hex String in Java for printing
       System.out.println("Byte array to Hex String in Java :                       " 
                                   + bytesToHexString(bytes));     
      
       //Apache commons codec to convert byte array to Hex String in Java
       String hex = Hex.encodeHexString(bytes);
       System.out.println("Byte array to Hexadecimal String using Apache commons:   " 
                                  + hex);
    }
   
    public static String bytesToHexString(byte[] bytes){
        StringBuilder sb = new StringBuilder();
        for(byte b : bytes){
            sb.append(String.format("%02x", b&0xff));
        }
        return sb.toString();
    }  
   
}

Output:
ab  cd
ab  cd
Byte array to Hex String in Java :                       616200056364
Byte array to Hexadecimal String using Apache commons:   616200056364

As I explained in the section issue with printing byte arrays, character after "ab" is not white space, it's a NUL ASCII character, but showing as white space here. Try running this Java program on your machine, and copying the first line of output, you can only copy the first two characters.

That's all on How to convert byte array to Hex String in Java. As I said, the byte array may contain some non-printable characters, which may produce a misleading value while printing them as normal String. It's always best to display the contents of the byte array as a hex string in Java.


Related  Java String Tutorials from Javarevisited Blog

4 comments :

Wouter Coekaerts said...

This also works, is short, and does not require an external library:
new BigInteger(bytes).toString(16)

Ashwin Jayaprakash said...

@Wouter That BigInt trick is a good one:

new BigInteger("testing $0002)--?!".getBytes()).toString(16)

new String(new BigInteger("74657374696e67202430303032292d2d3f21", 16).toByteArray())

Anonymous said...

BigInteger(bytes).toString(16) won't work as it will drop leading zeros

sandeep said...

thanks man.. it helped a lot..

Post a Comment