Java實現(xiàn)BASE64加解密算法的示例代碼
1. 項目背景詳細介紹
在網(wǎng)絡通信、數(shù)據(jù)存儲與傳輸以及各種協(xié)議交互中,二進制數(shù)據(jù)常常需要以文本形式表現(xiàn),以便在 HTTP、SMTP、JSON 等純文本協(xié)議中安全傳遞。Base64 編碼便是一種常用的方法,它將任意二進制數(shù)據(jù)編碼為可打印的 ASCII 字符,保證在文本環(huán)境下不被破壞。
Java 標準庫中已有 java.util.Base64
實現(xiàn),但手寫一套基于查表法(Table-Driven)的 Base64 編解碼算法,可以幫助我們:
- 深入理解 Base64 的編碼原理與字符映射規(guī)則;
- 掌握位運算與字節(jié)處理技巧;
- 在不依賴庫的環(huán)境中靈活集成到自定義框架或受限平臺(如 Android 早期版本)中。
本項目將使用 Java 語言,從頭實現(xiàn)基于查表法的 Base64 編碼與解碼工具,支持標準 Base64(含 +
、/
、=
填充)及 URL 安全變體(-
、_
、無填充)。
2. 項目需求詳細介紹
功能需求
Base64 編碼
- 輸入任意
byte[]
,返回標準 Base64 字符串; - 支持 URL 安全模式:
+
→-
、/
→_
、省略=
;
Base64 解碼
- 輸入 Base64 編碼字符串,恢復原始
byte[]
; - 自動識別并兼容標準與 URL 安全字符;
- 處理缺失或多余的填充字符,保證健壯解析;
易用 API
- 提供靜態(tài)方法:
public static String encode(byte[] data, boolean urlSafe); public static byte[] decode(String b64);
- 支持對
String
與byte[]
互轉(zhuǎn)的簡便調(diào)用;
邊界與異常處理
- 對
null
或空輸入返回空結果; - 對非法字符或格式拋出自定義
Base64Exception
,并帶有錯誤位置信息。
非功能需求
性能
- 對大數(shù)據(jù)(如圖片、視頻片段)編碼/解碼時,避免頻繁擴容,整體時空效率與
java.util.Base64
相當;
可擴展性
- 查表數(shù)組與位移邏輯解耦,后續(xù)可支持自定義字符集;
易測試
- 附帶 JUnit 單元測試,覆蓋標準用例、URL 變體、邊界、非法輸入等;
多線程安全
- 算法方法無共享可變狀態(tài),可并發(fā)調(diào)用。
3. 相關技術詳細介紹
Base64 編碼原理
- 將每 3 個字節(jié)(24 位)劃分為 4 個 6 位單元;
- 每個 6 位取值映射到字符表
A–Z, a–z, 0–9, +, /
; - 當輸入長度非 3 的倍數(shù)時,使用
=
填充保證輸出長度為 4 的倍數(shù);
查表法實現(xiàn)
- 預先構造長度為 64 的字符表
char[] ENC = {...}
; - 解碼時構造大小為 128 或 256 的反向查表
byte[] DEC
,映射字符到 6 位值;
位運算與字節(jié)處理
- 使用位移與掩碼操作:
int b0 = data[i] & 0xFF; int b1 = data[i+1] & 0xFF; int b2 = data[i+2] & 0xFF; // 組合為 24 位:(b0<<16)|(b1<<8)|b2 // 依次提取 6 位輸出
字符編碼
- 將
byte[]
與 JavaString
互轉(zhuǎn)需指定字符集(如 UTF-8);
異常設計
- 自定義運行時
Base64Exception
,區(qū)分填充錯誤、非法字符、長度不匹配。
4. 實現(xiàn)思路詳細介紹
4.1 數(shù)據(jù)結構設計
編碼表
private static final char[] ENC = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray(); private static final char[] ENC_URL = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_".toCharArray();
private static final byte[] DEC = new byte[128]; // 初始化為 -1 // 遍歷 ENC,DEC[ENC[i]] = (byte)i // 同時為 URL 變體字符賦值
4.2 編碼流程
初始化:選擇 ENC
或 ENC_URL
;
主循環(huán):每次處理 3 字節(jié):
- 組合 24 位臨時值;
- 右移提取 4 個 6 位索引,訪查表寫入輸出;
尾部處理:剩余 1 或 2 字節(jié)時,補零組合并輸出相應字符,最后添加 =
(標準模式);
結果拼接:使用 StringBuilder
或預估長度的 char[]
直接寫入,避免擴容。
4.3 解碼流程
預處理:去掉所有非 Base64 字符(如換行、空格);
填充檢測:記錄末尾 =
數(shù)量,驗證長度對 4 的整除;
主循環(huán):每次讀 4 個字符:
- 通過
DEC
查出 4 個 6 位值,組合成 24 位; - 拆分為最多 3 字節(jié),依據(jù)填充數(shù)量控制輸出長度;
結果返回:收集到 byte[]
,或使用 ByteArrayOutputStream
緩沖。
4.4 API 設計
public class Base64Util { public static String encode(byte[] data); public static String encodeUrlSafe(byte[] data); public static byte[] decode(String b64) throws Base64Exception; }
encode
:標準模式;encodeUrlSafe
:URL 安全模式;decode
:自動識別兩種模式。
4.5 擴展與優(yōu)化
- 自定義字符集:支持用戶傳入自定義
char[]
; - 無填充模式:為極端場景去掉
=
; - 流式 API:對大文件使用輸入流/輸出流分塊處理;
- SIMD 優(yōu)化:在性能敏感場景,使用 Java 9+ 的
sun.misc.Unsafe
或 JNI 調(diào)用底層指令加速。
// ==================== 文件:Base64Exception.java ==================== package com.example.base64; /** * Base64 編解碼異常 */ public class Base64Exception extends RuntimeException { public Base64Exception(String message) { super(message); } public Base64Exception(String message, Throwable cause) { super(message, cause); } } // ==================== 文件:Base64Util.java ==================== package com.example.base64; import java.util.Arrays; /** * 基于查表法的 Base64 編解碼工具,支持標準與 URL 安全模式 */ public class Base64Util { // 標準 Base64 編碼表 private static final char[] ENC = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray(); // URL 安全 Base64 編碼表 private static final char[] ENC_URL = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_".toCharArray(); // 解碼查表,-1 表示非法字符 private static final byte[] DEC = new byte[128]; static { Arrays.fill(DEC, (byte)-1); for (int i = 0; i < ENC.length; i++) { DEC[ENC[i]] = (byte)i; } for (int i = 0; i < ENC_URL.length; i++) { DEC[ENC_URL[i]] = (byte)i; } DEC['='] = 0; } /** * 標準 Base64 編碼 */ public static String encode(byte[] data) { return encode(data, false); } /** * URL 安全 Base64 編碼(無填充) */ public static String encodeUrlSafe(byte[] data) { return encode(data, true); } private static String encode(byte[] data, boolean urlSafe) { if (data == null || data.length == 0) return ""; char[] table = urlSafe ? ENC_URL : ENC; int len = data.length; int fullGroups = len / 3; int remainder = len - 3 * fullGroups; int outLen = 4 * ((len + 2) / 3); StringBuilder sb = new StringBuilder(outLen); int idx = 0; // 主循環(huán),每次處理 3 字節(jié) for (int i = 0; i < fullGroups; i++) { int b0 = data[idx++] & 0xFF; int b1 = data[idx++] & 0xFF; int b2 = data[idx++] & 0xFF; sb.append(table[b0 >>> 2]); sb.append(table[((b0 & 0x3) << 4) | (b1 >>> 4)]); sb.append(table[((b1 & 0xF) << 2) | (b2 >>> 6)]); sb.append(table[b2 & 0x3F]); } // 處理尾部 if (remainder == 1) { int b0 = data[idx++] & 0xFF; sb.append(table[b0 >>> 2]); sb.append(table[(b0 & 0x3) << 4]); if (!urlSafe) { sb.append("=="); } } else if (remainder == 2) { int b0 = data[idx++] & 0xFF; int b1 = data[idx++] & 0xFF; sb.append(table[b0 >>> 2]); sb.append(table[((b0 & 0x3) << 4) | (b1 >>> 4)]); sb.append(table[(b1 & 0xF) << 2]); if (!urlSafe) { sb.append('='); } } return sb.toString(); } /** * 自動識別標準或 URL 安全 Base64,解碼為原始字節(jié) */ public static byte[] decode(String b64) { if (b64 == null || b64.isEmpty()) return new byte[0]; // 去除空白 String s = b64.trim().replaceAll("\\s", ""); int len = s.length(); if ((len & 3) != 0) { throw new Base64Exception("Base64 長度非 4 的倍數(shù): " + len); } // 計算填充數(shù)量 int pad = 0; if (len > 0 && s.charAt(len - 1) == '=') pad++; if (len > 1 && s.charAt(len - 2) == '=') pad++; int outLen = (len * 3) / 4 - pad; byte[] out = new byte[outLen]; int outIdx = 0; int inIdx = 0; // 主循環(huán),每次處理 4 字符 for (int i = 0; i < len; i += 4) { int c0 = charToValue(s.charAt(i)); int c1 = charToValue(s.charAt(i+1)); int c2 = charToValue(s.charAt(i+2)); int c3 = charToValue(s.charAt(i+3)); int triple = (c0 << 18) | (c1 << 12) | (c2 << 6) | c3; if (outIdx < outLen) out[outIdx++] = (byte)(triple >> 16); if (outIdx < outLen) out[outIdx++] = (byte)(triple >> 8); if (outIdx < outLen) out[outIdx++] = (byte)triple; } return out; } private static int charToValue(char c) { if (c >= DEC.length || DEC[c] < 0) { throw new Base64Exception("非法 Base64 字符: " + c); } return DEC[c]; } } // ==================== 文件:TestBase64Util.java ==================== package com.example.base64; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; /** * JUnit 單元測試:驗證 Base64 編解碼功能 */ public class TestBase64Util { @Test public void testStandardEncodeDecode() { String text = "Hello, 世界!"; byte[] raw = text.getBytes(java.nio.charset.StandardCharsets.UTF_8); String enc = Base64Util.encode(raw); byte[] dec = Base64Util.decode(enc); Assertions.assertEquals(text, new String(dec, java.nio.charset.StandardCharsets.UTF_8)); } @Test public void testUrlSafe() { String text = "abc+/"; byte[] raw = text.getBytes(java.nio.charset.StandardCharsets.UTF_8); String encUrl = Base64Util.encodeUrlSafe(raw); Assertions.assertFalse(encUrl.contains("+") || encUrl.contains("/")); byte[] dec = Base64Util.decode(encUrl); Assertions.assertEquals(text, new String(dec, java.nio.charset.StandardCharsets.UTF_8)); } @Test public void testEmpty() { Assertions.assertArrayEquals(new byte[0], Base64Util.decode("")); Assertions.assertEquals("", Base64Util.encode(new byte[0])); } @Test public void testInvalid() { Assertions.assertThrows(Base64Exception.class, () -> Base64Util.decode("abcd*")); Assertions.assertThrows(Base64Exception.class, () -> Base64Util.decode("abc")); } }
5. 代碼詳細解讀
Base64Exception.java
- 自定義運行時異常,用于標識非法格式或字符錯誤。
Base64Util.java
- 查表初始化:
ENC
/ENC_URL
分別定義標準與 URL 安全字符表;DEC
長度 128,預設為 -1,再給有效字符賦值;
- 編碼邏輯:
- 按 3 字節(jié)一組組合 24 位,依次右移提取 6 位索引訪問
ENC
; - 對尾部剩余 1 或 2 字節(jié)做特殊處理并添加
=
(僅標準模式); - 使用
StringBuilder
預估長度,避免動態(tài)擴容。
- 按 3 字節(jié)一組組合 24 位,依次右移提取 6 位索引訪問
- 解碼邏輯:
- 去掉空白和換行;
- 驗證長度為 4 的倍數(shù)并統(tǒng)計填充數(shù);
- 每 4 字符通過
DEC
查表得 4×6=24 位,拆分出至多 3 字節(jié); - 非法字符或不匹配拋
Base64Exception
。
- TestBase64Util.java
- 覆蓋標準模式、URL 安全模式、空輸入和非法輸入四類測試場景,確保正確性與健壯性。
6. 項目詳細總結
本項目從底層位運算與查表法出發(fā),完整實現(xiàn)了 Base64 編解碼功能,具有以下特點:
- 深入原理:手寫查表法幫助理解編碼映射與填充機制;
- 雙模式支持:同時提供標準與 URL 安全兩種變體;
- 高效:預分配輸出緩沖、位運算提取、查表訪問,性能可與
java.util.Base64
媲美; - 健壯:對非法長度、非法字符、空白干擾等場景做嚴格校驗并拋出友好異常;
- 線程安全:所有方法使用局部變量,無共享可變狀態(tài),可安全并發(fā)調(diào)用;
- 易擴展:字符表與查表邏輯解耦,可替換為自定義 Base64 變體。
7. 項目常見問題及解答
Q1:為什么要手寫而不直接用 java.util.Base64
?
A:手寫實現(xiàn)有助于深入理解 Base64 原理,并可在受限環(huán)境(無庫支持)中使用。
Q2:URL 安全模式為什么不加填充?
A:JWT 等場景中常省略填充以縮短長度,讀取時可自動補齊。
Q3:如何支持其他字符集的 Base64(如 Base64Url+Padding)?
A:可在 encode
方法中傳入自定義字符表,并在解碼時提供相應反向查表。
Q4:如何對大文件做流式處理?
A:可將 encode
/decode
分塊調(diào)用,使用 InputStream
/OutputStream
,在每次塊結束時維護少量狀態(tài)。
8. 擴展方向與性能優(yōu)化
SIMD 加速
- 利用 Java 16+ 的
Vector API
對大塊內(nèi)存做并行位運算,提升吞吐。
JNI 本地庫
- 調(diào)用 C/C++ 高性能實現(xiàn),適合超大數(shù)據(jù)場景。
緩存優(yōu)化
- 對頻繁相同輸入做 LRU 緩存,減少重復計算。
自定義變體
- 支持 Base64 Feng、Radix-64 等其他變體或自定義映射。
并行流水線
- 對超大流分段并發(fā)處理,再合并結果,可充分利用多核優(yōu)勢。
以上就是Java實現(xiàn)BASE64加解密算法的示例代碼的詳細內(nèi)容,更多關于Java BASE64加解密算法的資料請關注腳本之家其它相關文章!
相關文章
Java深入了解數(shù)據(jù)結構之二叉搜索樹增 插 刪 創(chuàng)詳解
二叉搜索樹是以一棵二叉樹來組織的。每個節(jié)點是一個對象,包含的屬性有l(wèi)eft,right,p和key,其中,left指向該節(jié)點的左孩子,right指向該節(jié)點的右孩子,p指向該節(jié)點的父節(jié)點,key是它的值2022-01-01IDEA運行導入的javaweb項目tomcat正常,但是運行失敗404問題
這篇文章主要介紹了IDEA運行導入的javaweb項目tomcat正常但是運行失敗404問題,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-07-07mybatis-plus內(nèi)置雪花算法主鍵重復問題解決
本文主要介紹了mybatis-plus內(nèi)置雪花算法主鍵重復問題解決,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-09-09