【Base64】JDK里面实现Base64的API

原文出处: 成熟的毛毛虫的博客

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编码,用于处理常规的需求


1

2

3

4

5

6

// 编码

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里面的反斜线“/”


1

2

3

4

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”符结束。


1

2

3

4

5

6

7

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种,一旦有选择,则有必要将他们进行一次高低对比,性能测试是最直接的方式

首先来定义两个接口


1

2

3

4

5

6

7

8

9

10

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性能上会快一点,所以区分两组来测试


1

2

3

4

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的实现类


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

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的块,然后将他们分别编码和解码,记录时间,如下方法


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

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

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

时间: 2024-08-12 19:00:29

【Base64】JDK里面实现Base64的API的相关文章

JS base64 加密和 后台 base64解密(防止中文乱码)

直接上代码 1,js(2个文件,网上找的)  不要觉的长,直接复制下来就OK //UnicodeAnsi.js文件 //把Unicode转成Ansi和把Ansi转换成Unicode function UnicodeChr() { return '00A4,00A7,00A8,00B0,00B1,00B7,00D7,00E0,00E1,00E8,00E9,00EA,00EC,00ED,00F2,00F3,00F7,00F9,00FA,00FC,0101,0113,011B,012B,014D,01

Base64编码 图片与base64编码互转

package com.education.util; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; import java.io.*; /** * Created by jn-dinggao on 2016/2/4. */ public class Base64Util { // 将图片文件转化为字节数组字符串,并对其进行Base64编码处理 public static String GetImageStr(Stri

js base64位和c# Base64位转换

<script> /* 编码规则 Base64编码的思想是是采用64个基本的ASCII码字符对数据进行重新编码. 它将需要编码的数据拆分成字节数组. 以3个字节为一组.按顺序排列24 位数据,再把这24位数据分成4组,即每组6位. 再在每组的的最高位前补两个0凑足一个字节. 这样就把一个3字节为一组的数据重新编码成了4个字节. 当所要编码的数据的字节数不是3的整倍数, 也就是说在分组时最后一组不够3个字节. 这时在最后一组填充1到2个0字节. 并在最后编码完成后在结尾添加1到2个 “=”. *

JAVA将图片(本地或者网络资源)转为Base64字符串,将base64字符串存储为本地图片

网络资源代码 import java.io.ByteArrayOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder

java Base64 [ Encode And Decode In Base64 Using Java ]

http://www.javatips.net/blog/2011/08/how-to-encode-and-decode-in-base64-using-java http://commons.apache.org/proper/commons-codec/ 官方下载链接 Encode And Decode In Base64 Using Java explains about different techniques for Encode Base64 using java / Decode

java中Base64转码与解码(加密与解密)原理与使用

Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,大家可以查看RFC2045~RFC2049,上面有MIME的详细规范.Base64编码可用于在HTTP环境下传递较长的标识信息.例如,在Java Persistence系统Hibernate中,就采用了Base64来将一个较长的唯一标识符(一般为128-bit的UUID)编码为一个字符串,用作HTTP表单和HTTP GET URL中的参数.在其他应用程序中,也常常需要把二进制数据编码为适合放在URL(包括隐藏表单域)中的形式.此

Atitit.Base64编码原理与实现设计

Atitit.Base64编码原理与实现设计 1. Base64编码1 1.1. 为什么要用自己的base64编码方案1 2. Base64编码由来1 3. Base64编码原理1 3.1. 具体来说,转换方式可以分为四步:2 3.2. 注意2 3.3. Padding3 4. URL安全的Base64编码3 1. Base64编码 1.1. 为什么要用自己的base64编码方案 防止apache codec  jdk的jar冲突. 2. Base64编码由来 Base64最早是用来解决电子邮件

Java的3种Base64加密方法

Java的3种Base64加密方法 , 分别是 jdk默认实现的加密方式, 使用cc的加密方式和使用bc的加密方式 import java.io.IOException; import org.apache.commons.codec.binary.Base64; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; public class Main { public static void main(String[] ar

用javascript实现base64编码器

前面的话 base-64作为常见的编码函数,在基本认证.摘要认证以及一些HTTP扩展中得到了大量应用.在前端领域,也常常把图片转换为base-64编码在网络中传输.本文将详细介绍base64的原理及用js实现base64编码器的过程 原理 Base-64编码可以将任意一组字节转换成较长的常见文本字符序列,从而可以合法地作为首部字段值.Base-64编码将用户输入或二进制数据,打包成一种安全格式,将其作为HTTP首部字段的值发送出去,而无须担心其中包含会破坏HTTP分析程序的冒号.换行符或二进制值