简介
在Java7及7之前,要实代Base64编码,要么借助sun.misc.BASE64Encoder,或者apache commons-codec,再或者Guava、JAXB的DatatypeConverter,到了Java8,官方已经把Base64进行了重新优化,并直接放到了java.util包里了。
实现起来,比之前的都要简单优雅,性能卓越,无需引用第三方包。
sun的Base64被广泛使用,但sun、com.sun开头的包并非是公开的,sun没有提供API文档,引用时也会被提醒warning,不包含在Java平台的标准中,实现还与操作系统或jdk的供应商有关,比如openJDK就没有自带com.sun或sun开头的包。
Oracle也发表了声明,从JDK 1.7开始,java程序员不能调用JDK系统包中以sun开头引入的类。
声明的链接:http://www.oracle.com/technetwork/java/faq-sun-packages-142232.html
有人对sun、apache-codec、guava等多个Base64库进行了性能测试:sun的性能最差,java.util自带的Base64性能最好,java.util.Base64比sun有着近3倍性能的提升。功能方面,java.util.Base64还提供了对URL、MIME友好的编码器与解码器。
使用
以下是Base64对字符串和文件流的编码和解码:
1. 字符串的编码
可以将字符串转成Base64格式的串
String base64 = Base64.getEncoder().encodeToString("在Java 8中,Base64编码已经成为Java类库的标准。".getBytes("utf-8"));
2. 字符串解码
对Base64的串实现解码
String str = new String(Base64.getDecoder().decode("SmF2YTggQmFzZTY0IEphdmEgOCDmlrDnibnmgKcg5ZyoSmF2YSA45L" +
"itLEJhc2U2NOe8lueggeW3sue7j+aIkOS4ukphdmHnsbvlupPnmoTmoIflh4bjgIIgSmF2YSA4IOWGhee9ruS6hiBCYXNlNjQg57yW" +
"56CB55qE57yW56CB5Zmo5ZKM6Kej56CB5Zmo44CCIEJhc2U2NOW3peWFt+exu+aPkOS+m+S6huS4gOWll+mdmeaAgS4uLg=="),
"UTF-8");
3. 文件实现Base64编码
将1.png图片转成base64编码
File file = new File("C:\\Users\\Loufree\\Desktop\\1.png");
byte[] b = Files.readAllBytes(Paths.get(file.getAbsolutePath()));
String base64Str = Base64.getEncoder().encodeToString(b);
4. Base64解码成文件
Base64解码成文件。
String str = "ZG9ja2VyIGVjbGlwc2Xmj5Lku7YNCuWQjeensO+8mmRvY2tlci1uaWdodGx5DQrlnLDlnYDvvJpodHRwOi8vZG93bmxvYWQuZWNsaXBzZS5vcmcvbGludXh0b29scy91cGRhdGVzLWRvY2tlci1uaWdodGx5Lw==";
Files.write(Paths.get("D:/create.txt"), Base64.getDecoder().decode(str), StandardOpenOption.CREATE);
原理
为什么会有Base64编码呢?因为有些网络传送渠道并不支持所有的字节,例如传统的邮件只支持可见字符的传送,像ASCII码的控制字符就 不能通过邮件传送。这样用途就受到了很大的限制,比如图片二进制流的每个字节不可能全部是可见字符,所以就传送不了。最好的方法就是在不改变传统协议的情 况下,做一种扩展方案来支持二进制文件的传送。把不可打印的字符也能用可打印字符来表示,问题就解决了。Base64编码应运而生,Base64就是一种 基于64个可打印字符来表示二进制数据的表示方法。
有一个数组,里面有“A-Z, a-z, 0-9 , + , /”一共64个字符。然后对需要处理的的二进制数据做处理:每3个字节(24bit)一组,因此按照6bit一组为Base64的规则可以划为4组,每组6bit,刚好64位(对应数组的64个值)
Base64的码表只有64个字符, 如果要表达64个字符的话,使用6的bit即可完全表示(2的6次方为64)。 如果是字符串转换为Base64码, 会先把对应的字符串转换为ascll码表对应的数字, 然后再把数字转换为2进制, 比如a的ascll码味97, 97的二进制是:01100001, 把8个二进制提取成6个,剩下的2个二进制和后面的二进制继续拼接, 最后再把6个二进制码转换为Base64对于的编码
所以,Base64编码会把3字节的二进制数据编码为4字节的文本数据,长度增加33%,好处是编码后的文本数据可以在邮件正文、网页等直接显示。
如果要编码的二进制数据不是3的倍数,最后会剩下1个或2个字节怎么办?Base64用\x00字节在末尾补足后,再在编码的末尾加上1个或2个=号,表示补了多少字节,解码的时候,会自动去掉。
java8的Api提供了Basic编码、URL编码、MIME编码、对流的支持