2016年3月14日 星期一

[ Java 文章收集 ] Java如何進行Base64的編碼(Encode)與解碼(Decode)?

Source From Here
Introduction
Base64 是一種能將任意 Binary 資料用64種字元組合成字串的方法,而這個 Binary 資料和字串資料彼此之間是可以互相轉換的,十分方便。在實際應用上,Base64 除了能將Binary資料可視化之外,也常用來表示字串加密過後的內容。如果要使用Java程式語言來實作Base64的編碼與解碼功能,可以參考本篇文章的作法。

Java 上的 Base64

早期作法
早期在 Java 上做 Base64 的編碼與解碼,會使用到 JDK 裡 sun.misc 套件下的 BASE64Encoder 和 BASE64Decoder 這兩個類別,用法如下:
  1. final BASE64Encoder encoder = new BASE64Encoder();  
  2. final BASE64Decoder decoder = new BASE64Decoder();  
  3. final String text = "字串文字";  
  4. final byte[] textByte = text.getBytes("UTF-8");  
  5. //編碼  
  6. final String encodedText = encoder.encode(textByte);  
  7. System.out.println(encodedText);  
  8. //解碼  
  9. System.out.println(new String(decoder.decodeBuffer(encodedText), "UTF-8"));  
從以上程式可以發現,在Java用Base64一點都不難,不用幾行程式碼就解決了!只是這個 sun.misc 套件所提供的 Base64 功能,編碼和解碼的效率並不太好,而且在以後的 Java 版本可能就不被支援了,完全不建議使用

Apache Commons Codec 作法
Apache Commons Codec 有提供 Base64 的編碼與解碼功能,會使用到 org.apache.commons.codec.binary 套件下的 Base64 類別,用法如下:
  1. final Base64 base64 = new Base64();  
  2. final String text = "字串文字";  
  3. final byte[] textByte = text.getBytes("UTF-8");  
  4. //編碼  
  5. final String encodedText = base64.encodeToString(textByte);  
  6. System.out.println(encodedText);  
  7. //解碼  
  8. System.out.println(new String(base64.decode(encodedText), "UTF-8"));  
以上的程式碼看起來又比早期用 sun.misc 套件還要更精簡,效能實際執行起來也快了不少。缺點是需要引用 Apache Commons Codec,很麻煩。

Java 8 之後的作法
Java 8 的 java.util 套件中,新增了 Base64 的類別,可以用來處理 Base64 的編碼與解碼,用法如下:
  1. final Base64.Decoder decoder = Base64.getDecoder();  
  2. final Base64.Encoder encoder = Base64.getEncoder();  
  3. final String text = "字串文字";  
  4. final byte[] textByte = text.getBytes("UTF-8");  
  5. //編碼  
  6. final String encodedText = encoder.encodeToString(textByte);  
  7. System.out.println(encodedText);  
  8. //解碼  
  9. System.out.println(new String(decoder.decode(encodedText), "UTF-8"));  
與 sun.misc 套件和 Apache Commons Codec 所提供的 Base64 編解碼器來比較的話,Java 8 提供的 Base64 擁有更好的效能。實際測試編碼與解碼速度的話,Java 8 提供的Base64,要比sun.misc套件提供的還要快至少11倍,比 Apache Commons Codec 提供的還要快至少3倍。因此在 Java 上若要使用 Base64,這個 Java 8 底下的 java.util 套件所提供的 Base64 類別絕對是首選!

Performance Testing
底下代碼使用上面三種方法測試並列印出所需時間 (encode+decode):
  1. package test;  
  2.   
  3. import java.util.Random;  
  4.   
  5. import org.apache.commons.codec.binary.Base64;  
  6.   
  7. import sun.misc.BASE64Decoder;  
  8. import sun.misc.BASE64Encoder;  
  9. import flib.util.TimeStr;  
  10.   
  11. public class Base64Test {  
  12.     public static void SunAPI(String text) throws Exception  
  13.     {  
  14.         long st = System.currentTimeMillis();  
  15.         final BASE64Encoder encoder = new BASE64Encoder();    
  16.         final BASE64Decoder decoder = new BASE64Decoder();      
  17.         final byte[] textByte = text.getBytes("UTF-8");    
  18.         //編碼    
  19.         final String encodedText = encoder.encode(textByte);    
  20.         //System.out.println(encodedText);    
  21.         //解碼    
  22.         String decodeStr = new String(decoder.decodeBuffer(encodedText), "UTF-8");  
  23.         System.out.printf("SunAPI takes %s\n", TimeStr.toStringFrom(st));  
  24.     }  
  25.       
  26.     public static void ApacheCode(String text) throws Exception  
  27.     {  
  28.         long st = System.currentTimeMillis();  
  29.         final Base64 base64 = new Base64();           
  30.         final byte[] textByte = text.getBytes("UTF-8");    
  31.         //編碼    
  32.         final String encodedText = base64.encodeToString(textByte);    
  33.         //System.out.println(encodedText);    
  34.         //解碼    
  35.         String decodeStr = new String(base64.decode(encodedText), "UTF-8");  
  36.         System.out.printf("Apache Common Codec takes %s\n", TimeStr.toStringFrom(st));    
  37.     }  
  38.       
  39.     public static void JDK8Native(String text) throws Exception  
  40.     {  
  41.         long st = System.currentTimeMillis();  
  42.         final java.util.Base64.Decoder decoder = java.util.Base64.getDecoder();    
  43.         final java.util.Base64.Encoder encoder = java.util.Base64.getEncoder();      
  44.         final byte[] textByte = text.getBytes("UTF-8");    
  45.         //編碼    
  46.         final String encodedText = encoder.encodeToString(textByte);      
  47.         //解碼    
  48.         String decodeStr = new String(decoder.decode(encodedText), "UTF-8");    
  49.         System.out.printf("JDK8 Native API takes %s\n", TimeStr.toStringFrom(st));    
  50.     }  
  51.       
  52.       
  53.     public static void main(String args[]) throws Exception  
  54.     {  
  55.         // Generate testing string  
  56.         StringBuffer strBuf = new StringBuffer();  
  57.         String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";  
  58.         Random rdm = new Random();  
  59.         for(int i=0; i<100000; i++)   
  60.         {  
  61.             int r = rdm.nextInt(chars.length());  
  62.             strBuf.append(chars.substring(r, r+1));  
  63.         }  
  64.           
  65.         SunAPI(strBuf.toString());  
  66.         ApacheCode(strBuf.toString());  
  67.         JDK8Native(strBuf.toString());  
  68.     }  
  69. }  
不同電腦執行結果可能不同, 在我的筆電上執行速度 JDK8 API > Apache Common Codec > Sun API:
SunAPI takes 51 ms
Apache Common Codec takes 30 ms
JDK8 Native API takes 15 ms


沒有留言:

張貼留言

[Git 常見問題] error: The following untracked working tree files would be overwritten by merge

  Source From  Here 方案1: // x -----删除忽略文件已经对 git 来说不识别的文件 // d -----删除未被添加到 git 的路径中的文件 // f -----强制运行 #   git clean -d -fx 方案2: 今天在服务器上  gi...