一、Base64背景
在 Java 6 ( JDK 1.6 ) 之前, JDK 一直没有包含 Base64 的实现类。因此大部分人都使用 Sum/Orale JDK 里面的 sun.misc.BASE64Encode
和sun.misc.BASE64Decode
。然后这也成为很多 Java 开发者的习惯。一直沿用到今天的 Java8 中还有人在用。
JDK 1.6 虽然添加了 Base64 的实现。但是,非常隐秘,竟然是在 javax.xml.bind
包下的 DatastypeConvert
类中的两个静态方法 parseBase64Binary
和 printBase64Binary
.
Java 8 终于把 Base64 扶正了,在 java.util
包下提供了 Base64
类用于编码和解码 Base64 数据。
二、Java 8 Base64简介
Java 8 中的 java.util.Base64
类提供了三种类型的 Base64 编码解码格式:
1、 简单类型( simple ) : 编码字符只包含 A-Za-z0-9+/
等 64 个字符。且编码的时候不会包含任何换行符 ( \r
、 \n
、\r\n
)。解码的时候也只会解码 A-Za-z0-9+/
内的字符,超出的则会被拒绝。
2、 URL : 编码字符只包含 A-Za-z0-9+_
等 64 个字符。和 简单 相比,就是把 /
换成了 _
。因为没有 /
字符,因此这种编码方式非常适合 URL 和文件名等。
3、 MIME : 编码会被映射为 MIME 友好格式:每一行输出不超过 76 个字符,而且每行以 \r\n
符结束。但末尾行并不会包含 \r\n
。
三、内部类
java.util.Base64
还包含了两个内部静态类,分别实现了 RFC 4648 和 RFC 2045 中规范的 Base64 编码和解码方式。
内部类 | 说明 |
---|---|
static class Base64.Decoder | 该类实现使用 RFC 4648 和 RFC 2045 中规定的 Base64 解码方案解码数据 |
static class Base64.Encoder | 该类实现使用 RFC 4648 和 RFC 2045 中规定的 Base64 编码方案编码数据 |
四、静态方法
java.util.Base64
类提供的都是静态方法
//返回一个 Base64.Decoder 类型的 简单 解码器
public static Decoder getDecoder() {
return Decoder.RFC4648;
}
//返回一个 Base64.Encoder 类型的 简单 编码器
public static Encoder getEncoder() {
return Encoder.RFC4648;
}
//返回一个 Base64.Decoder 类型的 MIME 解码器
public static Decoder getMimeDecoder() {
return Decoder.RFC2045;
}
//返回一个 Base64.Encoder 类型的 MINE 编码器
public static Encoder getMimeEncoder() {
return Encoder.RFC2045;
}
//返回一个 Base64.Encoder 类型的使用特定长度和行分隔符的 MINE 编码器
public static Encoder getMimeEncoder(int lineLength, byte[] lineSeparator) {
Objects.requireNonNull(lineSeparator);
int[] base64 = Decoder.fromBase64;
for (byte b : lineSeparator) {
if (base64[b & 0xff] != -1)
throw new IllegalArgumentException(
"Illegal base64 line separator character 0x" + Integer.toString(b, 16));
}
if (lineLength <= 0) {
return Encoder.RFC4648;
}
return new Encoder(false, lineSeparator, lineLength >> 2 << 2, true);
}
//返回一个 Base64.Decoder 类型的 URL 和文件名安全的解码器
public static Decoder getUrlDecoder() {
return Decoder.RFC4648_URLSAFE;
}
//返回一个 Base64.Encoder 类型的 URL 和文件名安全的编码器public static Encoder getUrlEncoder() {
return Encoder.RFC4648_URLSAFE;
}
五、代码范例(一)基本的编码解码器
getDecoder()
和 getEncoder()
方法
package com.sjh.test.java8.base64;
import java.io.UnsupportedEncodingException;
import java.util.Base64;
public class Base64Test1 {
public static void main(String args[]) {
try {
String base64encodedString = Base64.getEncoder().encodeToString(
"Java 8 Base64 编码解码 - Java8新特性 - 二哥!".getBytes("utf-8"));
System.out.println(base64encodedString);
System.out.println();
byte[] base64decodedBytes = Base64.getDecoder().decode(base64encodedString);
System.out.println(new String(base64decodedBytes, "utf-8"));
} catch(UnsupportedEncodingException e) {
System.out.println("异常:" + e.getMessage());
}
}
}
运行结果:
/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/...com.sjh.test.java8.base64.Base64Test1
SmF2YSA4IEJhc2U2NCDnvJbnoIHop6PnoIEgLSBKYXZhOOaWsOeJueaApyAtIOS6jOWTpe+8gSA=
Java 8 Base64 编码解码 - Java8新特性 - 二哥!
Process finished with exit code 0
六、代码范例(二)URL 和文件名安全的编码解码器
getUrlEncoder()
和 getUrlDecoder()
方法
package com.sjh.test.java8.base64;
import java.io.UnsupportedEncodingException;
import java.util.Base64;
public class Base64Test2 {
public static void main(String args[]) {
try {
String base64encodedString = Base64.getUrlEncoder().encodeToString(
"Java 8 Base64 编码解码 - Java8新特性 - 二哥!".getBytes("utf-8"));
System.out.println(base64encodedString);
System.out.println();
byte[] base64decodedBytes = Base64.getUrlDecoder().decode(base64encodedString);
System.out.println(new String(base64decodedBytes, "utf-8"));
} catch(UnsupportedEncodingException e) {
System.out.println("异常:" + e.getMessage());
}
}
}
运行结果:
/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/...com.sjh.test.java8.base64.Base64Test2
SmF2YSA4IEJhc2U2NCDnvJbnoIHop6PnoIEgLSBKYXZhOOaWsOeJueaApyAtIOS6jOWTpe-8gSA=
Java 8 Base64 编码解码 - Java8新特性 - 二哥!
Process finished with exit code 0
七、代码范例(三)MIME Base64 编码解码器
getMimeEncoder()
和 getMimeDecoder()
无参方法
package com.sjh.test.java8.base64;
import java.io.UnsupportedEncodingException;
import java.util.Base64;
import java.util.UUID;
public class Base64Test3 {
public static void main(String args[]) {
try {
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < 10; ++i) {
stringBuilder.append(UUID.randomUUID().toString());
}
byte[] mimeBytes = stringBuilder.toString().getBytes("utf-8");
String mimeEncodedString = Base64.getMimeEncoder().encodeToString(mimeBytes);
System.out.println(mimeEncodedString);
System.out.println();
byte[] base64decodedBytes = Base64.getMimeDecoder().decode(mimeEncodedString);
System.out.println(new String(base64decodedBytes, "utf-8"));
} catch(UnsupportedEncodingException e) {
System.out.println("异常:" + e.getMessage());
}
}
}
运行结果:
/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/...com.sjh.test.java8.base64.Base64Test3
NjIyMTFlOGYtMDNlMi00NjFlLTgxOWYtMmZhNzk5NTYxOGMxNzIxYTQ3ZjEtMDk1Ni00OTM4LWIw
MjQtMTQwYmQ5YzQ1NjZjNDhjOTU5YzQtODI4OC00ZWE4LTg5ZDQtZTFiMjkxZGYyOGY1ZjYzMzNi
YTUtMTcyOC00NjUxLWE1MTQtNzU3NWRiMjJiMTc5ZjgyODZjYTctNWYyNS00YTU3LTlhNDctZDdk
M2Y4MDdiNjlkZTExN2YyODMtYjkzYi00YmRhLThlZWItZTZiNWYzZDUzMjJkYWI1ZDNlNWQtMjEz
NS00MDRmLWIzZmMtNzVhNDQyMjRiM2U5ZDcxZjE0ZjAtZTBlOC00MjEwLTlkYzYtOTJmZmQ4Njc2
ZTI2OGIyNzRmNmUtNDZkOS00NGFhLThjMTEtYTlhNjBhMDQwYTQzNDFkODBlNDQtYThiYS00ODcz
LTkzODgtMTA2MGNmODcyYTY5
62211e8f-03e2-461e-819f-2fa7995618c1721a47f1-0956-4938-b024-140bd9c4566c48c959c4-8288-4ea8-89d4-e1b291df28f5f6333ba5-1728-4651-a514-7575db22b179f8286ca7-5f25-4a57-9a47-d7d3f807b69de117f283-b93b-4bda-8eeb-e6b5f3d5322dab5d3e5d-2135-404f-b3fc-75a44224b3e9d71f14f0-e0e8-4210-9dc6-92ffd8676e268b274f6e-46d9-44aa-8c11-a9a60a040a4341d80e44-a8ba-4873-9388-1060cf872a69
Process finished with exit code 0
看不出来有 76 个字符分割
getMimeEncoder()
和 getMimeDecoder()
有参重载方法
package com.sjh.test.java8.base64;
import java.io.UnsupportedEncodingException;
import java.util.Base64;
import java.util.UUID;
public class BaseTest4 {
public static void main(String args[]) {
try {
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < 10; ++i) {
stringBuilder.append(UUID.randomUUID().toString());
}
byte[] mimeBytes = stringBuilder.toString().getBytes("utf-8");
String mimeEncodedString = Base64.getMimeEncoder(32,"@~@\n\n".getBytes("utf-8")).encodeToString(mimeBytes);
System.out.println(mimeEncodedString);
System.out.println();
byte[] base64decodedBytes = Base64.getMimeDecoder().decode(mimeEncodedString);
System.out.println(new String(base64decodedBytes, "utf-8"));
} catch(UnsupportedEncodingException e) {
System.out.println("异常:" + e.getMessage());
}
}
}
运行结果:
/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/...com.sjh.test.java8.base64.BaseTest4
MmIxZGFhMzktYjc1ZS00ZWFiLWIyYTMt@~@
YjVjNjJmMmQ4ZGRmYjE0NzI3Y2EtNTJk@~@
Yi00ZmZkLWE2NDMtMmZhM2RlMWNlMzk2@~@
YjlmYjViMDAtYjBmMi00NWYyLWE3NDkt@~@
Y2JjZTMxZjZkYjQ5MGYxMTI1YWQtMDQ2@~@
YS00M2UzLTkzMDgtMTFlZWE2MjFjMGQy@~@
NWNiMGE3YmMtYzM3Mi00M2EzLWE2OWMt@~@
ODczZGJmNTAzNzA5MjBiNzdlNjctNWU5@~@
OC00ZDUzLWI3MjAtNWJkMjM0ZjcyMGQy@~@
MDY0YzJlOTEtYzRkNi00NGRmLWFhYjAt@~@
NjIzNTBmMTRhOWQ5YTFiYzcwYmEtMTI1@~@
MC00OWIwLWJhZDktMDkzZGVjZjk3Nzcx@~@
YTIwZGUxYzItNmNiNy00ZTVlLWI4Njkt@~@
ZjA4YTdlNGFlY2RjNjlkZTZkYmItN2Q0@~@
Mi00YTU0LWEzYTUtZDAzYTFkMGYwNmM2
2b1daa39-b75e-4eab-b2a3-b5c62f2d8ddfb14727ca-52db-4ffd-a643-2fa3de1ce396b9fb5b00-b0f2-45f2-a749-cbce31f6db490f1125ad-046a-43e3-9308-11eea621c0d25cb0a7bc-c372-43a3-a69c-873dbf50370920b77e67-5e98-4d53-b720-5bd234f720d2064c2e91-c4d6-44df-aab0-62350f14a9d9a1bc70ba-1250-49b0-bad9-093decf97771a20de1c2-6cb7-4e5e-b869-f08a7e4aecdc69de6dbb-7d42-4a54-a3a5-d03a1d0f06c6
Process finished with exit code 0
end