最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java實現(xiàn)BASE64加解密算法的示例代碼

 更新時間:2025年07月17日 09:48:17   作者:Katie。  
Base64?編碼便是一種常用的方法,它將任意二進(jìn)制數(shù)據(jù)編碼為可打印的?ASCII?字符,保證在文本環(huán)境下不被破壞,本項目將使用?Java?語言,從頭實現(xiàn)基于查表法的?Base64?編碼與解碼工具,需要的朋友可以參考下

1. 項目背景詳細(xì)介紹

在網(wǎng)絡(luò)通信、數(shù)據(jù)存儲與傳輸以及各種協(xié)議交互中,二進(jìn)制數(shù)據(jù)常常需要以文本形式表現(xiàn),以便在 HTTP、SMTP、JSON 等純文本協(xié)議中安全傳遞。Base64 編碼便是一種常用的方法,它將任意二進(jìn)制數(shù)據(jù)編碼為可打印的 ASCII 字符,保證在文本環(huán)境下不被破壞。

Java 標(biāo)準(zhǔn)庫中已有 java.util.Base64 實現(xiàn),但手寫一套基于查表法(Table-Driven)的 Base64 編解碼算法,可以幫助我們:

  • 深入理解 Base64 的編碼原理與字符映射規(guī)則;
  • 掌握位運算與字節(jié)處理技巧;
  • 在不依賴庫的環(huán)境中靈活集成到自定義框架或受限平臺(如 Android 早期版本)中。

本項目將使用 Java 語言,從頭實現(xiàn)基于查表法的 Base64 編碼與解碼工具,支持標(biāo)準(zhǔn) Base64(含 +、/= 填充)及 URL 安全變體(-、_、無填充)。

2. 項目需求詳細(xì)介紹

功能需求

Base64 編碼

  • 輸入任意 byte[],返回標(biāo)準(zhǔn) Base64 字符串;
  • 支持 URL 安全模式:+-、/_、省略 =;

Base64 解碼

  • 輸入 Base64 編碼字符串,恢復(fù)原始 byte[]
  • 自動識別并兼容標(biāo)準(zhǔn)與 URL 安全字符;
  • 處理缺失或多余的填充字符,保證健壯解析;

易用 API

  • 提供靜態(tài)方法:
public static String encode(byte[] data, boolean urlSafe);
public static byte[] decode(String b64);
  • 支持對 Stringbyte[] 互轉(zhuǎn)的簡便調(diào)用;

邊界與異常處理

  • null 或空輸入返回空結(jié)果;
  • 對非法字符或格式拋出自定義 Base64Exception,并帶有錯誤位置信息。

非功能需求

性能

  • 對大數(shù)據(jù)(如圖片、視頻片段)編碼/解碼時,避免頻繁擴(kuò)容,整體時空效率與 java.util.Base64 相當(dāng);

可擴(kuò)展性

  • 查表數(shù)組與位移邏輯解耦,后續(xù)可支持自定義字符集;

易測試

  • 附帶 JUnit 單元測試,覆蓋標(biāo)準(zhǔn)用例、URL 變體、邊界、非法輸入等;

多線程安全

  • 算法方法無共享可變狀態(tài),可并發(fā)調(diào)用。

3. 相關(guān)技術(shù)詳細(xì)介紹

Base64 編碼原理

  • 將每 3 個字節(jié)(24 位)劃分為 4 個 6 位單元;
  • 每個 6 位取值映射到字符表 A–Z, a–z, 0–9, +, /
  • 當(dāng)輸入長度非 3 的倍數(shù)時,使用 = 填充保證輸出長度為 4 的倍數(shù);

查表法實現(xiàn)

  • 預(yù)先構(gòu)造長度為 64 的字符表 char[] ENC = {...};
  • 解碼時構(gòu)造大小為 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[] 與 Java String 互轉(zhuǎn)需指定字符集(如 UTF-8);

異常設(shè)計

  • 自定義運行時 Base64Exception,區(qū)分填充錯誤、非法字符、長度不匹配。

4. 實現(xiàn)思路詳細(xì)介紹

4.1 數(shù)據(jù)結(jié)構(gòu)設(shè)計

編碼表

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 編碼流程

初始化:選擇 ENCENC_URL

主循環(huán):每次處理 3 字節(jié):

  • 組合 24 位臨時值;
  • 右移提取 4 個 6 位索引,訪查表寫入輸出;

尾部處理:剩余 1 或 2 字節(jié)時,補零組合并輸出相應(yīng)字符,最后添加 =(標(biāo)準(zhǔn)模式);

結(jié)果拼接:使用 StringBuilder 或預(yù)估長度的 char[] 直接寫入,避免擴(kuò)容。

4.3 解碼流程

預(yù)處理:去掉所有非 Base64 字符(如換行、空格);

填充檢測:記錄末尾 = 數(shù)量,驗證長度對 4 的整除;

主循環(huán):每次讀 4 個字符:

  • 通過 DEC 查出 4 個 6 位值,組合成 24 位;
  • 拆分為最多 3 字節(jié),依據(jù)填充數(shù)量控制輸出長度;

結(jié)果返回:收集到 byte[],或使用 ByteArrayOutputStream 緩沖。

4.4 API 設(shè)計

public class Base64Util {
    public static String encode(byte[] data);
    public static String encodeUrlSafe(byte[] data);
    public static byte[] decode(String b64) throws Base64Exception;
}
  • encode:標(biāo)準(zhǔn)模式;
  • encodeUrlSafe:URL 安全模式;
  • decode:自動識別兩種模式。

4.5 擴(kuò)展與優(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 編解碼工具,支持標(biāo)準(zhǔn)與 URL 安全模式
 */
public class Base64Util {
    // 標(biāo)準(zhǔn) 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;
    }
 
    /**
     * 標(biāo)準(zhǔn) 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();
    }
 
    /**
     * 自動識別標(biāo)準(zhǔn)或 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. 代碼詳細(xì)解讀

Base64Exception.java

  • 自定義運行時異常,用于標(biāo)識非法格式或字符錯誤。

Base64Util.java

  • 查表初始化
    • ENC/ENC_URL 分別定義標(biāo)準(zhǔn)與 URL 安全字符表;
    • DEC 長度 128,預(yù)設(shè)為 -1,再給有效字符賦值;
  • 編碼邏輯
    • 按 3 字節(jié)一組組合 24 位,依次右移提取 6 位索引訪問 ENC
    • 對尾部剩余 1 或 2 字節(jié)做特殊處理并添加 =(僅標(biāo)準(zhǔn)模式);
    • 使用 StringBuilder 預(yù)估長度,避免動態(tài)擴(kuò)容。
  • 解碼邏輯
    • 去掉空白和換行;
    • 驗證長度為 4 的倍數(shù)并統(tǒng)計填充數(shù);
    • 每 4 字符通過 DEC 查表得 4×6=24 位,拆分出至多 3 字節(jié);
    • 非法字符或不匹配拋 Base64Exception。
  • TestBase64Util.java
    • 覆蓋標(biāo)準(zhǔn)模式、URL 安全模式、空輸入和非法輸入四類測試場景,確保正確性與健壯性。

6. 項目詳細(xì)總結(jié)

本項目從底層位運算與查表法出發(fā),完整實現(xiàn)了 Base64 編解碼功能,具有以下特點:

  • 深入原理:手寫查表法幫助理解編碼映射與填充機(jī)制;
  • 雙模式支持:同時提供標(biāo)準(zhǔn)與 URL 安全兩種變體;
  • 高效:預(yù)分配輸出緩沖、位運算提取、查表訪問,性能可與 java.util.Base64 媲美;
  • 健壯:對非法長度、非法字符、空白干擾等場景做嚴(yán)格校驗并拋出友好異常;
  • 線程安全:所有方法使用局部變量,無共享可變狀態(tài),可安全并發(fā)調(diào)用;
  • 易擴(kuò)展:字符表與查表邏輯解耦,可替換為自定義 Base64 變體。

7. 項目常見問題及解答

Q1:為什么要手寫而不直接用 java.util.Base64?
A:手寫實現(xiàn)有助于深入理解 Base64 原理,并可在受限環(huán)境(無庫支持)中使用。

Q2:URL 安全模式為什么不加填充?
A:JWT 等場景中常省略填充以縮短長度,讀取時可自動補齊。

Q3:如何支持其他字符集的 Base64(如 Base64Url+Padding)?
A:可在 encode 方法中傳入自定義字符表,并在解碼時提供相應(yīng)反向查表。

Q4:如何對大文件做流式處理?
A:可將 encode/decode 分塊調(diào)用,使用 InputStream/OutputStream,在每次塊結(jié)束時維護(hù)少量狀態(tài)。

8. 擴(kuò)展方向與性能優(yōu)化

SIMD 加速

  • 利用 Java 16+ 的 Vector API 對大塊內(nèi)存做并行位運算,提升吞吐。

JNI 本地庫

  • 調(diào)用 C/C++ 高性能實現(xiàn),適合超大數(shù)據(jù)場景。

緩存優(yōu)化

  • 對頻繁相同輸入做 LRU 緩存,減少重復(fù)計算。

自定義變體

  • 支持 Base64 Feng、Radix-64 等其他變體或自定義映射。

并行流水線

  • 對超大流分段并發(fā)處理,再合并結(jié)果,可充分利用多核優(yōu)勢。

以上就是Java實現(xiàn)BASE64加解密算法的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于Java BASE64加解密算法的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • MyBatis中的resultMap簡要概述

    MyBatis中的resultMap簡要概述

    這篇文章主要介紹了MyBatis中的resultMap簡要概述的相關(guān)資料,需要的朋友可以參考下
    2016-07-07
  • Spring官網(wǎng)下載各版本jar包的方法

    Spring官網(wǎng)下載各版本jar包的方法

    這篇文章主要介紹了Spring官網(wǎng)下載各版本jar包的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-04-04
  • Java線上死鎖問題從定位到解決的全鏈路指南

    Java線上死鎖問題從定位到解決的全鏈路指南

    在分布式系統(tǒng)高并發(fā)場景下,死鎖如同定時炸彈,隨時可能引發(fā)服務(wù)雪崩,本文將分享一套完整的死鎖應(yīng)對策略,結(jié)合實戰(zhàn)案例與生產(chǎn)級解決方案,助你快速化解危機(jī),需要的朋友可以參考下
    2025-06-06
  • Java實現(xiàn)圖片比率縮放

    Java實現(xiàn)圖片比率縮放

    這篇文章主要為大家詳細(xì)介紹了Java通過Thumbnails實現(xiàn)圖片比率縮放,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • Java?volatile關(guān)鍵字特性講解下篇

    Java?volatile關(guān)鍵字特性講解下篇

    JMM要求保證可見性、原子性、有序性,volatile可以保證其中的兩個,本篇文章具體驗證volatile的可見性,不原子性和禁重排,同時解決volatile的不保證原子性,讓代碼具有原子性
    2022-12-12
  • springcloud3 Sentinel的搭建及案例操作方法

    springcloud3 Sentinel的搭建及案例操作方法

    Sentinel是分布式系統(tǒng)流量控制的哨兵,阿里開源的一套服務(wù)容錯的綜合性解決方案,這篇文章主要介紹了springcloud3 Sentinel的搭建以及案例操作,需要的朋友可以參考下
    2023-01-01
  • Java中的IO流原理和流的分類詳解

    Java中的IO流原理和流的分類詳解

    這篇文章主要介紹了Java中的IO流原理和流的分類詳解,Java?io流是Java編程語言中用于輸入和輸出操作的一種機(jī)制。它提供了一組類和接口,用于處理不同類型的數(shù)據(jù)流,包括文件、網(wǎng)絡(luò)連接、內(nèi)存等,需要的朋友可以參考下
    2023-10-10
  • 詳解如何在Java項目中實現(xiàn)信號的連續(xù)接收

    詳解如何在Java項目中實現(xiàn)信號的連續(xù)接收

    在Java項目中,信號的連續(xù)接收是一項重要的任務(wù),特別是在處理異步事件或者需要對外部事件做出響應(yīng)時,本篇博客將介紹如何在Java項目中實現(xiàn)信號的連續(xù)接收,包括信號的監(jiān)聽、處理和停止等步驟,需要的朋友可以參考下
    2023-11-11
  • OpenFeign調(diào)用服務(wù)請求頭丟失Token的解決

    OpenFeign調(diào)用服務(wù)請求頭丟失Token的解決

    這篇文章主要介紹了OpenFeign調(diào)用服務(wù)請求頭丟失Token的解決方法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • SpringBoot熱部署啟動關(guān)閉流程詳解

    SpringBoot熱部署啟動關(guān)閉流程詳解

    Spring?Boot啟動熱部署是一種技術(shù),它能讓開發(fā)者在不重啟應(yīng)用程序的情況下實時更新代碼。這樣可以提高開發(fā)效率,避免頻繁重啟應(yīng)用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2023-04-04

最新評論

资阳市| 马鞍山市| 翼城县| 张家口市| 衡阳市| 晋城| 神池县| 囊谦县| 保山市| 博罗县| 全州县| 嘉峪关市| 兰坪| 通化市| 龙川县| 舞阳县| 思南县| 凤凰县| 滕州市| 西峡县| 和林格尔县| 佛冈县| 抚松县| 额敏县| 客服| 洛南县| 印江| 赤壁市| 东辽县| 云南省| 平武县| 营山县| 唐山市| 班戈县| 贵溪市| 青河县| 吉安市| 南华县| 大连市| 来宾市| 文化|