Original source: The blog of the mature Caterpillar
BASE64 encoding is a commonly used character encoding and is used in many places. But Base64 is not a cryptographic decryption algorithm in the security domain. The effect of security is very poor, and easy to crack, his core role should be to transmit data correctness, some gateways or systems can only use ASCII characters. Base64 is a method used to convert non-ASCII character data into ASCII characters, and Base64 is particularly suitable for fast data transfer under Http,mime protocol.
implementation of Base64 API within JDK
Prior to JDK1.6, the JDK core class had no BASE64 implementation class, and it was suggested that the sun/oracle JDK Sun.misc.BASE64Encoder and Sun.misc.BASE64Decoder, the advantage of using them is that there is no need to rely on third-party libraries, and the downside is that they may be removed in future versions (with a warning from MAVEN compilation), with poor performance and performance testing later.
Another implementation of BASE64 was added to the JDK1.6, Javax.xml.bind.DatatypeConverter two static methods Parsebase64binary and Printbase64binary, Hidden under the Javax.xml.bind package, not known by many developers.
In Java 8 under the Java.util package implementation of the BASE64 codec API, and performance, API is easy to understand, the following shows the use of this class example.
Java.util.Base64
This class provides a set of static methods for obtaining the following three BASE64 codecs:
1) Basic code: is a standard BASE64 encoding for handling general requirements
123456 |
//encoding string asB64 = Base64.getencoder (). encodetostring ( .getbytes ( "Utf-8" system.out.println (asB64); //output is: c29tzsbzdhjpbmc= //decoding byte [] asbytes = Base64.getdecoder (). Decode ( system.out.println ( new string (asbytes, //output is: Some string |
2) URL encoding: Use underscore to replace backslash "/" Inside URL
1234 |
String urlEncoded = Base64.getUrlEncoder().encodeToString( "subjects?abcd" .getBytes( "utf-8" )); System.out.println( "Using URL Alphabet: " + urlEncoded); // 输出为: Using URL Alphabet: c3ViamVjdHM_YWJjZA== |
3) MIME encoding: Generates BASE64 output using basic alphanumeric characters, and is friendly to MIME format: output of each line is no more than 76 character, and each line ends with a "\ r \ n" symbol.
1234567 |
stringbuilder sb = new stringbuilder (); for ( int t = 0 10 ; ++t) {    sb.append (Uuid.randomuuid (). ToString ()); } byte [] Toencode = Sb.tostring (). GetBytes ( "Utf-8" string mimeencoded = Base64.getmimeencoder (). encodetostring (Toencode); system.out.println (mimeencoded); |
third-party implementations of BASE64 APIs
The first is the common Apache Commons Codec library inside the org.apache.commons.codec.binary.Base64;
The second one is the static method of the Com.google.common.io.BaseEncoding.base64 () in Google Guava Library;
The third one is net.iharder.Base64, the jar package is a class;
The last one, known as BASE64 encoding speed of the fastest MigBase64, and is 10 years ago the realization, to now whether can maintain the title, test a test will know;
Base64 Coding Performance Test
There are 7 kinds of implementation of the BASE64 code, JDK 3, third-party implementation of 4, once there is a choice, it is necessary to do a high and low contrast, performance testing is the most direct way
First of all, define two interfaces.
12345678910 |
private static interface Base64Codec
{
public String encode(
final byte
[] data);
public byte
[] decode(
final String base64)
throws IOException;
}
private static interface Base64ByteCodec
{
public byte
[] encodeBytes(
final byte
[] data);
public byte
[] decodeBytes(
final byte
[] base64)
throws IOException;
}
|
The two interface difference is that one of the interface method parameters receives a byte array, which returns a byte array because byte->byte is faster than String->byte or byte->string performance, so differentiate between two groups to test
1234 |
private static final Base64Codec[] m_codecs = {
new GuavaImpl(),
new JavaXmlImpl(),
new Java8Impl(),
new SunImpl(),
new ApacheImpl(),
new MiGBase64Impl(),
new IHarderImpl() };
private static final Base64ByteCodec[] m_byteCodecs = {
new ApacheImpl(),
new Java8Impl(),
new MiGBase64Impl(),
new IHarderImpl() };
|
Seen from the above, which supports byte->byte only 4 API;
7 implementation classes for a Base64
1234567891011121314151617181920212223242526272829 |
private static class Java8Impl
implements Base64Codec, Base64ByteCodec
{
private final Base64.Decoder m_decoder = Base64.getDecoder();
private final Base64.Encoder m_encoder = Base64.getEncoder();
@Override
public String encode(
byte
[] data) {
return m_encoder.encodeToString(data);
}
@Override
public byte
[] decode(String base64)
throws IOException {
return m_decoder.decode(base64);
}
public byte
[] encodeBytes(
byte
[] data) {
return m_encoder.encode( data );
}
public byte
[] decodeBytes(
byte
[] base64)
throws IOException {
return m_decoder.decode( base64 );
}
}
private static class JavaXmlImpl
implements Base64Codec
//no byte[] implementation
{
public String encode(
byte
[] data) {
return DatatypeConverter.printBase64Binary( data );
}
public byte
[] decode(String base64)
throws IOException {
return DatatypeConverter.parseBase64Binary( base64 );
}
}
..............
|
The following code is basically a variety of API implementation BASE64 code, it is not listed in detail.
The main test method is to generate a random number of 100M, divided into 100byte or 1000byte blocks, and then encode and decode them separately, recording the time, as follows
123456789101112131415161718 |
private static TestResult testByteCodec(
final Base64ByteCodec codec,
final List<
byte
[]> buffers )
throws IOException {
final List<
byte
[]> encoded =
new ArrayList<
byte
[]>( buffers.size() );
final long start = System.currentTimeMillis();
for (
final byte
[] buf : buffers )
encoded.add( codec.encodeBytes(buf) );
final long encodeTime = System.currentTimeMillis() - start;
final List<
byte
[]> result =
new ArrayList<
byte
[]>( buffers.size() );
final long start2 = System.currentTimeMillis();
for (
final byte
[] ar : encoded )
result.add( codec.decodeBytes(ar) );
final long decodeTime = System.currentTimeMillis() - start2;
for (
int i =
0
; i < buffers.size(); ++i )
{
if ( !Arrays.equals( buffers.get( i ), result.get( i ) ) )
System.out.println(
"Diff at pos = " + i );
}
return new TestResult( encodeTime /
1000.0
, decodeTime /
1000.0 );
}
|
Test results
JVM Parameters:-xms512m-xmx4g
Everything is obvious, from the above, Sun's performance is not very good, iharder and MigBase64 performance can be accepted, the legendary MigBase64 performance first, that is the past, in this test results, the new JAVA8 base64 run the best speed, Javaxml performance followed.
Summary
If you need a good performance, reliable Base64 codec, do not look outside the JDK, java8 inside the java.util.Base64 and java6 hidden deep javax.xml.bind.DatatypeConverter, Both of them are good choices.
All the code in this article is in Http://git.oschina.net/benhail/javase8-sample, welcome to focus on the download
BASE64 API implemented in "BASE64" jdk