Java 8新特性 - (11)Base64编解码

分享到:

早期处理BASE64编码, 需借助外部依赖:commons-codec,sun.misc.BASE64Decoder或JAXB的DatatypeConverter。Java 8实现了BASE64编解码API,它包含到java.util包。

java.util.Base64工具类提供了一套静态方法获取下面三种BASE64编解码器:

  1. Basic编码
  2. URL编码
  3. MIME编码

Basic编码

Basic编码是标准的BASE64编码,用于处理常规的需求:输出的内容不添加换行符,而且输出的内容由字母加数字组成。

1// 编码
2String asB64 = Base64.getEncoder().encodeToString("some string".getBytes("utf-8"));
3System.out.println(asB64); // 输出为: c29tZSBzdHJpbmc=
4 
5// 解码
6byte[] asBytes = Base64.getDecoder().decode("c29tZSBzdHJpbmc=");
7System.out.println(new String(asBytes, "utf-8")); // 输出为: some string

URL编码

URL编码也是经常的需求,但由于URL对反斜线“/”有特殊的意义,因此URL编码需要替换掉它,使用下划线替换

1String basicEncoded = Base64.getEncoder().encodeToString("subjects?abcd".getBytes("utf-8"));
2System.out.println("Using Basic Alphabet: " + basicEncoded);
3 
4String urlEncoded = Base64.getUrlEncoder().encodeToString("subjects?abcd".getBytes("utf-8"));
5System.out.println("Using URL Alphabet: " + urlEncoded);
6
7// 输出为:
8Using Basic Alphabet: c3ViamVjdHM/YWJjZA==
9Using URL Alphabet: c3ViamVjdHM_YWJjZA==

MIME编码

MIME编码器会使用基本的字母数字产生BASE64输出,而且对MIME格式友好:每一行输出不超过76个字符,而且每行以“\r\n”符结束。

 1StringBuilder sb = new StringBuilder();
 2for (int t = 0; t < 10; ++t) {
 3  sb.append(UUID.randomUUID().toString());
 4}
 5 
 6byte[] toEncode = sb.toString().getBytes("utf-8");
 7String mimeEncoded = Base64.getMimeEncoder().encodeToString(toEncode);
 8System.out.println(mimeEncoded);
 9
10// 输出为:
11NDU5ZTFkNDEtMDVlNy00MDFiLTk3YjgtMWRlMmRkMWEzMzc5YTJkZmEzY2YtM2Y2My00Y2Q4LTk5
12ZmYtMTU1NzY0MWM5Zjk4ODA5ZjVjOGUtOGMxNi00ZmVjLTgyZjctNmVjYTU5MTAxZWUyNjQ1MjJj
13NDMtYzA0MC00MjExLTk0NWMtYmFiZGRlNDk5OTZhMDMxZGE5ZTYtZWVhYS00OGFmLTlhMjgtMDM1
14ZjAyY2QxNDUyOWZiMjI3NDctNmI3OC00YjgyLThiZGQtM2MyY2E3ZGNjYmIxOTQ1MDVkOGQtMzIz
15Yi00MDg0LWE0ZmItYzkwMGEzNDUxZTIwOTllZTJiYjctMWI3MS00YmQzLTgyYjUtZGRmYmYxNDA4
16Mjg3YTMxZjMxZmMtYTdmYy00YzMyLTkyNzktZTc2ZDc5ZWU4N2M5ZDU1NmQ4NWYtMDkwOC00YjIy
17LWIwYWItMzJiYmZmM2M0OTBm

流的封装

java.util.Base64类封装了所有的BASE64编码器和解码器,还支持流的封装——这是一个非常优雅的构造——包括编码和效率都很高(无需缓冲Buffer)——即编码器和解码器的输入和输出无需缓冲Buffer。

下面的例子来说明了编码器是怎样封装FileOutputStream,以及解码器是怎样封装FileInputStream的,两者皆不需要缓冲Buffer:

 1public void wrapping() throws IOException {
 2  String src = "This is the content of any resource read from somewhere" +
 3    " into a stream. This can be text, image, video or any other stream.";
 4 
 5  // 编码器封装OutputStream, 文件/tmp/buff-base64.txt的内容是BASE64编码的形式
 6  try (OutputStream os = Base64.getEncoder().wrap(newFileOutputStream("/tmp/buff-base64.txt"))) {
 7    os.write(src.getBytes("utf-8"));
 8  }
 9 
10  // 解码器封装InputStream, 以及以流的方式解码, 无需缓冲
11  // is being consumed. There is no need to buffer the content of the file just for decoding it.
12  try (InputStream is = Base64.getDecoder().wrap(newFileInputStream("/tmp/buff-base64.txt"))) {
13    int len;
14    byte[] bytes = new byte[100];
15    while ((len = is.read(bytes)) != -1) {
16      System.out.print(new String(bytes, 0, len, "utf-8"));
17    }
18  }
19}

参考: