Java 8 中Base64编码已经成为Java标准类库的一部分,并内置了Base64编码的编码器和解码器。Base64工具类提供了一套静态方法获取三种BASE64的编码和解码器:标准、URL、MIME。
由于很多信息的编码是无法直接打印的。Base64编码要求把每三个8Bit的字节转换为四个6Bit的字节,然后把6Bit再添加两位高位0,组成四个8Bit的字节,转换后字符串将是初始长度的4/3倍。经Base64处理后,不可显示的乱码信息(如密文)就可以打印出来(不过打印信息主要是用于展示,但并不适用于人类阅读)。
Base64编码的其他规则:
1,把3个字节变成4个字节;
2,每76个字符加一个换行符;
3,最后的结束符也要处理。
标准的Base64编码不适合直接放在URL里传输,因为URL编码器会把标准Base64编码中的“/”和“+”字符转换成形如“%XX”的形式,而“%”号在保存到数据库时还需要进行转换,因为在SQL查询语言中“%”号是通配符。
为了解决此问题产生了一个改正版本的Base64编码,改正措施是末尾填充“=”,并将标准Base64编码中的“+”和“/”分别用“-”和“_”代替。
为了更好地理解Base64编码,下面提供一个简单的Base64编码器实现程序:
import java.io.ByteArrayOutputStream;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class Base64OutputStream extends FilterOutputStream{
private static char[] toBase64 = { 'A','B','C','D','E','F','G','H','I','J',
'K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d',
'e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
'0','1','2','3','4','5','6','7','8','9','+','/' };
private int col = 0;
private int i = 0;
private int[] inbuf = new int[3];
public static String base64Encode(String str)
{ //把普通String字符串转换成Base编码的字符串
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
Base64OutputStream out = new Base64OutputStream(bOut);
try {
out.write(str.getBytes());
out.flush();
} catch (IOException e) { e.printStackTrace(); }
return bOut.toString();
}
public Base64OutputStream(OutputStream out) {
super(out);
}
@Override
public void flush() throws IOException {
if (i>0&&col>=76) {
super.write('\n');
col = 0;
}
if (i==1) { //inbuf[1]是最后一个字节
super.write(toBase64[(inbuf[0]&0xFC)>>2]);
super.write(toBase64[(inbuf[0]&0x03)<<4]);
super.write('=');
super.write('=');
} else if (i==2) { //inbuf[2]是最后一个字节
super.write(toBase64[(inbuf[0]&0xFC)>>2]);
super.write(toBase64[((inbuf[0]&0x03)<<4)|((inbuf[1]&0xF0)>>4)]);
super.write(toBase64[(inbuf[1]&0x0F)<<2]);
super.write('=');
}
}
@Override
public void write(int c) throws IOException {
inbuf[i++] = c;
if (i==3) {
if (col>=76) {
super.write('\n');
col = 0;
}
super.write(toBase64[(inbuf[0]&0xFC)>>2]);
super.write(toBase64[((inbuf[0]&0x03)<<4)|((inbuf[1]&0xF0)>>4)]);
super.write(toBase64[((inbuf[1]&0x0F)<<2)|((inbuf[2]&0xC0)>>6)]);
super.write(toBase64[inbuf[2]&0x3F]);
col += 4;
i = 0;
}
}
public static void main(String[] args) {
final String[] text = {"珍禽栩栩枝间舞",
"满园花发艳无双",
"丰姿挺秀鲜似锦",
"群芳岂肯妒天香"};
String encoded = null ;
for (int i = 0; i < text.length; i++) {
encoded = base64Encode(text[i]);
System.out.println( encoded );
}
}
}
程序的运行效果图:
程序说明:
我们在测试时使用了普通的可显示文本作为输入参数。实际上,Base64编码器的使用场景并不是给普通可显示文本进行编码,而是把不可显示的文本信息进行编码,从而变成可显示和打印的文本。有一个使用场景是对普通的可显示文本进行加密后,其密文通常无法正常显示和打印,此时用Base64编码器处理后,就可把密文显示或打印出来。打印出来的信息也是加密的。
Java 8 中Base64编码已经成为Java标准类库的一部分,并内置了Base64编码的编码器和解码器。
我们也顺便来演示一下JDK8中自带的Base64编码的编码器和解码器用法,测试程序如下:
import java.nio.charset.StandardCharsets;
import java.util.Base64;
public class Base64Test {
public static void main(String[] args) {
final String[] text = {"珍禽栩栩枝间舞",
"满园花发艳无双",
"丰姿挺秀鲜似锦",
"群芳岂肯妒天香"};
String[] encoded = {null,null,null,null};
System.out.println( "编码后的Base64编码文本:" );
for (int i = 0; i < text.length; i++) {
encoded[i] = Base64.getEncoder().encodeToString( text[i].getBytes( StandardCharsets.UTF_8 ) );
System.out.println( encoded[i] );
}
System.out.println( "解码后变成原文:" );
String decoded;
for (int i = 0; i < encoded.length; i++) {
decoded = new String( Base64.getDecoder().decode( encoded[i] ), StandardCharsets.UTF_8 );
System.out.println( decoded );
}
}
}
其测试效果图,如下图所示:
说明:
Java 8 中Base64编码器的算法与我们前文自编的Base64编码器有差异,所以,编码后的Base64编码文本并不一致。