Java 8 does contain its own implementation of Base64. However, I found one slightly disturbing difference. To illustrate, I will provide a code example:
My codec wrapper:
public interface MyCodec { static String apacheDecode(String encodedStr) { return new String(Base64.decodeBase64(encodedStr), Charset.forName("UTF-8")); } static String apacheEncode(String decodedStr) { byte[] decodedByteArr = decodedStr.getBytes(Charset.forName("UTF-8")); return Base64.encodeBase64String(decodedByteArr); } static String javaDecode(String encodedStr) { return new String(java.util.Base64.getDecoder().decode(encodedStr), Charset.forName("UTF-8")); } static String javaEncode(String decodedStr) { byte[] decodedByteArr = decodedStr.getBytes(Charset.forName("UTF-8")); return java.util.Base64.getEncoder().encodeToString(decodedByteArr); } }
Test Class:
public class CodecDemo { public static void main(String[] args) { String decodedText = "Hello World!"; String encodedApacheText = MyCodec.apacheEncode(decodedText); String encodedJavaText = MyCodec.javaEncode(decodedText); System.out.println("Apache encoded text: " + MyCodec.apacheEncode(encodedApacheText)); System.out.println("Java encoded text: " + MyCodec.javaEncode(encodedJavaText)); System.out.println("Encoded results equal: " + encodedApacheText.equals(encodedJavaText)); System.out.println("Apache decode Java: " + MyCodec.apacheDecode(encodedJavaText)); System.out.println("Java decode Java: " + MyCodec.javaDecode(encodedJavaText)); System.out.println("Apache decode Apache: " + MyCodec.apacheDecode(encodedApacheText)); System.out.println("Java decode Apache: " + MyCodec.javaDecode(encodedApacheText)); } }
OUTPUT:
Apache encoded text: U0dWc2JHOGdWMjl5YkdRaA0K Java encoded text: U0dWc2JHOGdWMjl5YkdRaA== Encoded results equal: false Apache decode Java: Hello World! Java decode Java: Hello World! Apache decode Apache: Hello World! Exception in thread "main" java.lang.IllegalArgumentException: Illegal base64 character d at java.util.Base64$Decoder.decode0(Base64.java:714) at java.util.Base64$Decoder.decode(Base64.java:526) at java.util.Base64$Decoder.decode(Base64.java:549)
Notice that the Apache encoded text contain additional line breaks (white spaces) at the end. Therefore, in order for my codec to yield the same result regardless of Base64 implementation, I had to call trim() on the Apache encoded text. In my case, I simply added the aforementioned method call to the my codec's apacheDecode() as follows:
return Base64.encodeBase64String(decodedByteArr).trim();
Once this change was made, the results are what I expected to begin with:
Apache encoded text: U0dWc2JHOGdWMjl5YkdRaA== Java encoded text: U0dWc2JHOGdWMjl5YkdRaA== Encoded results equal: true Apache decode Java: Hello World! Java decode Java: Hello World! Apache decode Apache: Hello World! Java decode Apache: Hello World!
CONCLUSION: If you want to switch from Apache Base64 to Java, you must:
- Decode encoded text with your Apache decoder.
- Encode resulting (plain) text with Java.
If you switch without following these steps, most likely you will run into problems. That is how I made this discovery.
sun.**