private static final char[] ENCODE_TABLE = new char[64];
private static final byte[] DECODE_TABLE = new byte[256]; // -1 非法
static {
// 編碼表
int idx = 0;
for (char c = 'A'; c <= 'Z'; c++) ENCODE_TABLE[idx++] = c;
for (char c = 'a'; c <= 'z'; c++) ENCODE_TABLE[idx++] = c;
for (char c = '0'; c <= '9'; c++) ENCODE_TABLE[idx++] = c;
ENCODE_TABLE[idx++] = '+'; ENCODE_TABLE[idx++] = '/';
// 解碼表
Arrays.fill(DECODE_TABLE, (byte) -1);
for (int i = 0; i < 64; i++) DECODE_TABLE[ENCODE_TABLE[i]] = (byte) i;
DECODE_TABLE['='] = -2; // 填充標記
}
public static String encode(byte[] data) {
if (data == null) return null;
int len = data.length;
if (len == 0) return "";
int outLen = (len + 2) / 3 * 4; // 含填充
char[] out = new char[outLen];
int op = 0, ip = 0;
while (ip < len) {
int b0 = data[ip++] & 0xFF;
int b1 = ip < len ? data[ip++] & 0xFF : 0;
int b2 = ip < len ? data[ip++] & 0xFF : 0;
int triple = (b0 << 16) | (b1 << 8) | b2;
out[op++] = ENCODE_TABLE[(triple >>> 18) & 0x3F];
out[op++] = ENCODE_TABLE[(triple >>> 12) & 0x3F];
out[op++] = (ip > len + 1) ? '=' : ENCODE_TABLE[(triple >>> 6) & 0x3F]; // 倒數第二字符
out[op++] = (ip > len) ? '=' : ENCODE_TABLE[triple & 0x3F]; // 最後字符
}
return new String(out);
}
public static byte[] decode(String s) throws IllegalArgumentException {
if (s == null) return null;
s = s.trim();
if (s.isEmpty()) return new byte[0];
if (s.length() % 4 != 0) throw new IllegalArgumentException("長度非 4 倍數");
// 計算有效字符數 (排除填充)
int pad = 0;
if (s.endsWith("==")) pad = 2;
else if (s.endsWith("=")) pad = 1;
int dataLen = (s.length() / 4) * 3 - pad;
byte[] out = new byte[dataLen];
int op = 0;
for (int i = 0; i < s.length(); i += 4) {
int v0 = decodeChar(s.charAt(i));
int v1 = decodeChar(s.charAt(i+1));
int v2 = decodeChar(s.charAt(i+2));
int v3 = decodeChar(s.charAt(i+3));
int triple = (v0 << 18) | (v1 << 12) | (v2 << 6) | v3;
out[op++] = (byte) (triple >>> 16);
if (op < dataLen) out[op++] = (byte) (triple >>> 8);
if (op < dataLen) out[op++] = (byte) triple;
}
return out;
}
private static int decodeChar(char c) {
if (c >= DECODE_TABLE.length) throw new IllegalArgumentException("非 ASCII 字符: " + c);
int v = DECODE_TABLE[c];
if (v < 0) throw new IllegalArgumentException("非法 Base64 字符: " + c);
return v;
}
| 實現 | 相對速度 | 備註 |
|---|---|---|
| 手寫位運算 (上述) | 1.0x | 基準 |
| Java 8 `Base64.getEncoder()` | ~1.2x | 內部使用 `sun.misc.Base64` 或向量化 |
| Apache Commons Codec | ~0.9x | 功能豐富但稍慢 |
**直接使用 `java.util.Base64` (Java 8+)**:標準、高效、無依賴、支援 MIME/URL/無填充多種模式。手寫版本僅供教學、面試、極度受限環境 (無 JRE、嵌入式) 參考。