Java8新特性之Base64详解_动力节点Java学院整理
base64 编码是一种常用的字符编码,在很多地方都会用到。但base64不是安全领域下的加密解密算法。能起到安全作用的效果很差,而且很容易破解,他核心作用应该是传输数据的正确性,有些网关或系统只能使用ascii字符。base64就是用来将非ascii字符的数据转换成ascii字符的一种方法,而且base64特别适合在http,mime协议下快速传输数据。
jdk里面实现base64的api
在jdk1.6之前,jdk核心类一直没有base64的实现类,有人建议用sun/oracle jdk里面的sun.misc.base64encoder 和 sun.misc.base64decoder,使用它们的优点就是不需要依赖第三方类库,缺点就是可能在未来版本会被删除(用maven编译会发出警告),而且性能不佳,后面会有性能测试。
jdk1.6中添加了另一个base64的实现,javax.xml.bind.datatypeconverter两个静态方法parsebase64binary 和 printbase64binary,隐藏在javax.xml.bind包下面,不被很多开发者知道。
在java 8在java.util包下面实现了base64编解码api,而且性能不俗,api也简单易懂,下面展示下这个类的使用例子。
java.util.base64
该类提供了一套静态方法获取下面三种base64编解码器:
1)basic编码:是标准的base64编码,用于处理常规的需求
// 编码 string asb64 = base64.getencoder().encodetostring("some string".getbytes("utf-8")); system.out.println(asb64); // 输出为: c29tzsbzdhjpbmc= // 解码 byte[] asbytes = base64.getdecoder().decode("c29tzsbzdhjpbmc="); system.out.println(new string(asbytes, "utf-8")); // 输出为: some string
2)url编码:使用下划线替换url里面的反斜线“/”
string urlencoded = base64.geturlencoder().encodetostring("subjects?abcd".getbytes("utf-8")); system.out.println("using url alphabet: " + urlencoded); // 输出为: using url alphabet: c3viamvjdhm_ywjjza==
3)mime编码:使用基本的字母数字产生base64输出,而且对mime格式友好:每一行输出不超过76个字符,而且每行以“\r\n”符结束。
stringbuilder sb = new stringbuilder(); for (int t = 0; t < 10; ++t) { sb.append(uuid.randomuuid().tostring()); } byte[] toencode = sb.tostring().getbytes("utf-8"); string mimeencoded = base64.getmimeencoder().encodetostring(toencode); system.out.println(mimeencoded);
第三方实现base64的api
首先便是常用的apache commons codec library里面的org.apache.commons.codec.binary.base64;
第二个便是google guava库里面的com.google.common.io.baseencoding.base64() 这个静态方法;
第三个是net.iharder.base64,这个jar包就一个类;
最后一个,号称base64编码速度最快的migbase64,而且是10年前的实现,到现在是否能保持这个称号,测一测便知道;
base64编码性能测试
上面讲了一共7种实现base64编码,jdk里面3种,第三方实现4种,一旦有选择,则有必要将他们进行一次高低对比,性能测试是最直接的方式
首先来定义两个接口
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; }
两个接口区别就是其中一个接口方法参数接收byte数组,返回byte数组,因为byte->byte相比string->byte或者byte->string性能上会快一点,所以区分两组来测试
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() };
从上面看出,其中支持byte->byte只有4中api;
7个base64的实现类
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 ); } } ..............
后面代码基本就是各种api实现base64的代码了,就不详细列出。
主要测试手段是,生成100m的随机数,分成100byte或者1000byte的块,然后将他们分别编码和解码,记录时间,如下方法
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 ); }
测试结果
jvm参数:-xms512m -xmx4g
一切都很明显了,从上面看出,sun的表现不是很好,iharder和migbase64性能可以接受,传说migbase64性能第一,那也是过去了,在这次测试结果中,新的java8 base64运行速度最好,javaxml表现次之。
总结
如果你需要一个性能好,可靠的base64编解码器,不要找jdk外面的了,java8里面的java.util.base64以及java6中隐藏很深的javax.xml.bind.datatypeconverter,他们两个都是不错的选择。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
推荐阅读
-
Java8新特性之Base64详解_动力节点Java学院整理
-
Java8新特性之泛型的目标类型推断_动力节点Java学院整理
-
Java8新特性之StampedLock_动力节点Java学院整理
-
Java8新特性之lambda的作用_动力节点Java学院整理
-
Java8新特性之类型注解_动力节点Java学院整理
-
Java8新特性之再见Permgen_动力节点Java学院整理
-
Java8新特性之精简的JRE详解_动力节点Java学院整理
-
Java新特性之Nashorn_动力节点Java学院整理
-
Java8新特性之深入解析日期和时间_动力节点Java学院整理
-
Java8新特性之lambda(动力节点Java学院整理)