Thursday, March 28, 2013

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

We often needs to convert byte arrays to Hex String in Java, In order to print byte array contents in readable format. Since many cryptographic algorithm e.g. MD5 return hash value as byte array, In order to see and compare those byte array, you need to convert byte array to Hex String. As we have seen, while generating MD5 check sum 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 open source library e.g. Apache commons codec to create Hex String from byte array in Java. Commons codec provides a utility class Hex, which contains a encodeHexString() method to create Hex String from byte array. It's one of the best option 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 issue with printing byte array as normal String, and 2 examples to convert byte array into Hexadecimal String in Java.


Issue with Printing Byte array 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 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 there 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 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 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 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 are easy to read, compared to binary or decimal format as it takes less digits.

These are some notable benefits of printing byte array as 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 String format method. In this Java program, we will see two examples to convert byte array to Hexadecimal String. In first example, we have used core Java, and in 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 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 in your machine, and copying first line of output, you can only copy first two characters.

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

Related  Java String Tutorials from Javarevisited Blog

3 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

Post a Comment