首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Base64 編碼 Java 實作全解析:從原理到生產級代碼

     編輯:Java 程式設計入門

前言:為什麼需要 Base64?

Base64 將任意二進位資料編碼為 64 個可列印 ASCII 字元 (A-Z, a-z, 0-9, +, /),解決郵件傳輸 (MIME)、XML/JSON 嵌入二進位、URL 參數傳遞、資料庫儲存 Blob 等場景的「非文本安全」問題。每 3 位元組 (24 bits) 轉為 4 個 Base64 字元 (4×6=24 bits),編碼後體積膨脹約 33%。

編碼原理圖解

輸入: "men" (3 bytes = 24 bits)
m(109) e(101) n(110)
二進位: 01101101 01100101 01101110
分組:   011011 010110 010101 101110  (4組 × 6 bits)
十進位:   27     22     21     46
Base64:    b      W      V      u
結果: "bWVu"

不足 3 bytes 時以 '=' 補齊至 4 字元:
"me"  → "bWU="
"m"   → "bQ=="

MIME 規範要求

  • 每行最大 76 字元 (含換行)
  • 行尾使用 CRLF (\r\n)
  • 補齊字元 '=' 僅出現在結尾

手工實作核心邏輯 (教學用)

public class MIMEBase64 {
    private static final char[] BASE64_TABLE = 
        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray();
    
    public static void encode(String filename, BufferedWriter out) throws IOException {
        byte[] bytes = Files.readAllBytes(Paths.get(filename));
        int n = bytes.length;
        if (n == 0) return;
        
        int fullGroups = n / 3;
        int remainder = n % 3;
        int lineLength = 0;
        
        // 處理完整 3-byte 組
        for (int i = 0; i < fullGroups * 3; i += 3) {
            int b1 = bytes[i] & 0xFF;
            int b2 = bytes[i+1] & 0xFF;
            int b3 = bytes[i+2] & 0xFF;
            
            out.write(BASE64_TABLE[b1 >>> 2]);
            out.write(BASE64_TABLE[(b1 & 0x03) << 4 | (b2 >>> 4)]);
            out.write(BASE64_TABLE[(b2 & 0x0F) << 2 | (b3 >>> 6)]);
            out.write(BASE64_TABLE[b3 & 0x3F]);
            
            if (++lineLength >= 19) {  // 19×4=76 字元
                out.write('\n');
                lineLength = 0;
            }
        }
        
        // 處理尾部剩餘 1 或 2 bytes
        if (remainder == 2) {
            int b1 = bytes[n-2] & 0xFF;
            int b2 = bytes[n-1] & 0xFF;
            out.write(BASE64_TABLE[b1 >>> 2]);
            out.write(BASE64_TABLE[(b1 & 0x03) << 4 | (b2 >>> 4)]);
            out.write(BASE64_TABLE[(b2 & 0x0F) << 2]);
            out.write('=');
        } else if (remainder == 1) {
            int b1 = bytes[n-1] & 0xFF;
            out.write(BASE64_TABLE[b1 >>> 2]);
            out.write(BASE64_TABLE[(b1 & 0x03) << 4]);
            out.write('=');
            out.write('=');
        }
        
        if (lineLength > 0) out.write('\n');
    }
}

生產環境標準庫用法 (JDK 8+)

基本編解碼

// 編碼
String encoded = Base64.getEncoder().encodeToString(bytes);
String encodedUrlSafe = Base64.getUrlEncoder().encodeToString(bytes);  // URL 安全版 (-_ 替代 +/)

// 解碼
byte[] decoded = Base64.getDecoder().decode(encodedString);
byte[] decodedUrlSafe = Base64.getUrlDecoder().decode(encodedString);

// MIME 格式 (自動換行 76 字元)
String mimeEncoded = Base64.getMimeEncoder().encodeToString(bytes);

流式處理 (大檔案/網路流)

// 編碼輸出流
try (OutputStream os = Base64.getEncoder().wrap(outputStream)) {
    os.write(data);
}

// 解碼輸入流
try (InputStream is = Base64.getDecoder().wrap(inputStream)) {
    byte[] buffer = new byte[8192];
    int len;
    while ((len = is.read(buffer)) != -1) { /* 處理 */ }
}

常見坑點與最佳實踐

坑點解決方案
字串獲取位元組未指定編碼必須指定 str.getBytes(StandardCharsets.UTF_8)
URL 參數含 + / = 導致解析錯誤使用 Base64.getUrlEncoder() (輸出 - _ 無補齊)
大檔案載入記憶體 OOM使用流式 wrap() 邊讀邊碼
解碼拋出 IllegalArgumentException輸入含非法字元或長度非 4 倍數,預處理過濾/補齊
Android 與 JDK 行為差異Android 早期版本用 android.util.Base64,API 26+ 對齊 JDK

效能對比

  • JDK 內建 Base64:原生優化、向量化指令、最快
  • Apache Commons Codec:早期 JDK 6/7 替代方案,效能略遜
  • 手工實作:教學用途,生產環境嚴禁使用

總結

Base64 是二進位資料進入文本世界的通用橋樑。理解其 3→4 位元組分組、位移遮罩、補齊機制是基本功,但生產代碼必須使用 JDK 內建 java.util.Base64 (JDK 8+)。針對 URL、MIME、大檔案等場景選擇對應 Encoder/Decoder,善用流式 API 避免記憶體壓力。舊版本專案可引入 Apache Commons Codec 或升級 JDK。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved