zoukankan      html  css  js  c++  java
  • Java 8新特性探究(十一)Base64详解

    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个字符,而且每行以“ ”符结束。

    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 Base64CodecBase64ByteCodec
        {
            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 testByteCodecfinal 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,他们两个都是不错的选择。

    本篇中所有代码都在http://git.oschina.net/benhail/javase8-sample ,欢迎大家去关注下载

    原文地址:https://my.oschina.net/benhaile/blog/267738
  • 相关阅读:
    Azure 虚拟机安全加固整理
    AzureARM 使用 powershell 扩容系统磁盘大小
    Azure Linux 云主机使用Root超级用户登录
    Open edX 配置 O365 SMTP
    powershell 根据错误GUID查寻错误详情
    azure 创建redhat镜像帮助
    Azure Powershell blob中指定的vhd创建虚拟机
    Azure Powershell 获取可用镜像 PublisherName,Offer,Skus,Version
    Power BI 连接到 Azure 账单,自动生成报表,可刷新
    Azure powershell 获取 vmSize 可用列表的命令
  • 原文地址:https://www.cnblogs.com/jpfss/p/10038930.html
Copyright © 2011-2022 走看看