天天看點

Java 8實作BASE64編解碼Java 8實作BASE64編解碼

版權聲明:本文為部落客chszs的原創文章,未經部落客允許不得轉載。 https://blog.csdn.net/chszs/article/details/17027649

Java 8實作BASE64編解碼

作者:chszs,轉載需注明。部落格首頁:

http://blog.csdn.net/chszs

Java一直缺少BASE64編碼 API,以至于通常在項目開發中會選用第三方的API實作。但是,Java 8實作了BASE64編解碼API,它包含到java.util包。下面我會對Java 8的BASE64 API做一個介紹。

java.util.Base64工具類提供了一套靜态方法擷取下面三種BASE64編解碼器:

1)Basic編碼

2)URL編碼

3)MIME編碼

Basic編碼是标準的BASE64編碼,用于處理正常的需求:輸出的内容不添加換行符,而且輸出的内容由字母加數字組成。下面是用法:

// 編碼
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
           

與早期處理BASE64編碼需求相比,不可能更簡單了。因為無需外部依賴:commons-codec或sun.misc.BASE64Decoder或JAXB的DatatypeConverter。

URL編碼也是我們經常會面對的需求,但由于URL對反斜線“/”有特殊的意義,是以URL編碼需要替換掉它,使用下劃線替換。比如下面的例子:

String basicEncoded = Base64.getEncoder().encodeToString("subjects?abcd".getBytes("utf-8"));
System.out.println("Using Basic Alphabet: " + basicEncoded);
 
String urlEncoded = Base64.getUrlEncoder().encodeToString("subjects?abcd".getBytes("utf-8"));
System.out.println("Using URL Alphabet: " + urlEncoded);
// 輸出為:
Using Basic Alphabet: c3ViamVjdHM/YWJjZA==
Using URL Alphabet: c3ViamVjdHM_YWJjZA==
           

上面的例子可以看出,如果是使用基本的編碼器,那麼輸出可能會包含反斜線“/”字元,但是如果使用URL編碼器,那麼輸出的内容對URL來說是安全的。

MIME編碼器會使用基本的字母數字産生BASE64輸出,而且對MIME格式友好:每一行輸出不超過76個字元,而且每行以“\r\n”符結束。比如下面的例子:

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);
// 輸出為:
NDU5ZTFkNDEtMDVlNy00MDFiLTk3YjgtMWRlMmRkMWEzMzc5YTJkZmEzY2YtM2Y2My00Y2Q4LTk5
ZmYtMTU1NzY0MWM5Zjk4ODA5ZjVjOGUtOGMxNi00ZmVjLTgyZjctNmVjYTU5MTAxZWUyNjQ1MjJj
NDMtYzA0MC00MjExLTk0NWMtYmFiZGRlNDk5OTZhMDMxZGE5ZTYtZWVhYS00OGFmLTlhMjgtMDM1
ZjAyY2QxNDUyOWZiMjI3NDctNmI3OC00YjgyLThiZGQtM2MyY2E3ZGNjYmIxOTQ1MDVkOGQtMzIz
Yi00MDg0LWE0ZmItYzkwMGEzNDUxZTIwOTllZTJiYjctMWI3MS00YmQzLTgyYjUtZGRmYmYxNDA4
Mjg3YTMxZjMxZmMtYTdmYy00YzMyLTkyNzktZTc2ZDc5ZWU4N2M5ZDU1NmQ4NWYtMDkwOC00YjIy
LWIwYWItMzJiYmZmM2M0OTBm
           

java.util.Base64類封裝了所有的BASE64編碼器和解碼器,還支援流的封裝——這是一個非常優雅的構造——包括編碼和效率都很高(無需緩沖Buffer)——即編碼器和解碼器的輸入和輸出無需緩沖Buffer。下面我們以一個例子來說明編碼器是怎樣封裝FileOutputStream,以及解碼器是怎樣封裝FileInputStream的,兩者皆不需要緩沖Buffer:

public void wrapping() throws IOException {
  String src = "This is the content of any resource read from somewhere" +
    " into a stream. This can be text, image, video or any other stream.";

  // 編碼器封裝OutputStream, 檔案/tmp/buff-base64.txt的内容是BASE64編碼的形式
  try (OutputStream os = Base64.getEncoder().wrap(newFileOutputStream("/tmp/buff-base64.txt"))) {
    os.write(src.getBytes("utf-8"));
  }

  // 解碼器封裝InputStream, 以及以流的方式解碼, 無需緩沖
  // is being consumed. There is no need to buffer the content of the file just for decoding it.
  try (InputStream is = Base64.getDecoder().wrap(newFileInputStream("/tmp/buff-base64.txt"))) {
    int len;
    byte[] bytes = new byte[100];
    while ((len = is.read(bytes)) != -1) {
      System.out.print(new String(bytes, 0, len, "utf-8"));
    }
  }
}