【算法记录】Java - Base64编码解码源码

Base64编码表

索引 对应字符 索引 对应字符 索引 对应字符 索引 对应字符
0 A 17 R 34 i 51 z
1 B 18 S 35 j 52 0
2 C 19 T 36 k 53 1
3 D 20 U 37 l 54 2
4 E 21 V 38 m 55 3
5 F 22 W 39 n 56 4
6 G 23 X 40 o 57 5
7 H 24 Y 41 p 58 6
8 I 25 Z 42 q 59 7
9 J 26 a 43 r 60 8
10 K 27 b 44 s 61 9
11 L 28 c 45 t 62 +
12 M 29 d 46 u 63 /
13 N 30 e 47 v
14 O 31 f 48 w
15 P 32 g 49 x
16 Q 33 h 50 y

Base64基本原理

  • 一、要编码的数据3个byte为一组,共3*8=24个bit
  • 二、24个bit每6个一组,共分为四组
  • 三、6位所表示数字的最大值为(2 ^ 6) - 1 = 63,刚好对应上面的编码表,即3个byte的原始数据编码后得到4个byte的数据
  • 四、如果要编码的数据长度不是3的倍数,即最后一组数据凑不出24个bit,那么在最后面补位0

tips:

// 要编码的数据
String src = "mengxin";
// 对应的字节数组
byte[] src = new byte[]{109, 101, 110, 103, 120, 105, 110}
// 要编码的数据长度为7,前面的[109, 101, 110, 103, 120, 105]正常编码,后面剩下一个110对应的二进制为01101110
// 补0后得到011011100000000000000000
// 每6位为一组,共四组
// (1) 011011:对应的数字为27,这一组含有原本的位,所以正常查找编码表
// (2) 100000:对应的数字为32,这一组含有原本的位,所以正常查找编码表
// (3) 000000:对应的数字为0,这一组完全是由补位得到的,所以填充“=”
// (4) 000000:对应的数字为0,这一组完全是由补位得到的,所以填充“=”



// 解码原理相同,逆推即可

这里有一个动画讲解教程:

【【动画密码学】Base64编码&解码算法】https://www.bilibili.com/video/BV1Hp4y1g7Ex/?share_source=copy_web&vd_source=2c801bab51441760fc5e8a76d502c656

这里是我练习的编码解码源代码,比较简陋,仅作为理解使用,开发环境还是使用别人开发好的

  • 没有进行细节处理,不喜勿喷,我的算法能力确实比较差
import java.io.ByteArrayOutputStream;

public class Base64 {
    private static final String Base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

    public static void main(String[] args) throws Exception {
        System.out.println(Encode("mengxin".getBytes()));
        System.out.println(new String(Decode("bWVuZ3hpbg==")));
    }

    /**
     * Base64编码
     * @param src 要编码的数据
     * @return Base64编码后的字符串
     */
    public static String Encode(byte[] src) {
        int paddings = src.length % 3;
        StringBuffer sb = new StringBuffer();
        int i = 0;
        for (; i < src.length - paddings; i += 3) {
            sb.append(Base64EncodeChars.charAt(src[i] >> 2));
            sb.append(Base64EncodeChars.charAt(((src[i] & 3) << 4) | (src[i + 1] >> 4)));
            sb.append(Base64EncodeChars.charAt(((src[i + 1] & 15) << 2) | (src[i + 2] >> 6)));
            sb.append(Base64EncodeChars.charAt(src[i + 2] & 63));
        }
        if (paddings == 2) {
            sb.append(Base64EncodeChars.charAt(src[i] >> 2));
            sb.append(Base64EncodeChars.charAt(((src[i] & 3) << 4) | (src[i + 1] >> 4)));
            sb.append(Base64EncodeChars.charAt((src[i + 1] & 15) << 2));
            sb.append("=");
        } else if (paddings == 1) {
            sb.append(Base64EncodeChars.charAt(src[i] >> 2));
            sb.append(Base64EncodeChars.charAt((src[i] & 3) << 4));
            sb.append("=");
            sb.append("=");
        }
        return sb.toString();
    }

    /**
     * Base64解码
     * @param src 要解码的字符串
     * @return Base64解码后的数据
     */

    public static byte[] Decode(String src) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        int i = 0;
        for (; i < src.length() - 4; i += 4) {
            int i1 = Base64EncodeChars.indexOf(src.charAt(i));
            int i2 = Base64EncodeChars.indexOf(src.charAt(i + 1));
            int i3 = Base64EncodeChars.indexOf(src.charAt(i + 2));
            int i4 = Base64EncodeChars.indexOf(src.charAt(i + 3));
            baos.write((i1 << 2) | (i2 >> 4));
            baos.write(((i2 & 15) << 4) | (i3 >> 2));
            baos.write(((i3 & 3) << 6) | i4);
            //System.out.println(i1 + "|" + i2 + "|" + i3 + "|" + i4);
        }
        int i1 = Base64EncodeChars.indexOf(src.charAt(i)) << 2 | (Base64EncodeChars.indexOf(src.charAt(i + 1)) >> 4);
        if ('=' == src.charAt(i + 2)){
            baos.write(i1);
        } else {
            int i2 = (Base64EncodeChars.indexOf(src.charAt(i + 1)) << 4) | (Base64EncodeChars.indexOf(src.charAt(i + 2)) >> 2);
            if ('=' == src.charAt(i + 3)) {
                baos.write(i1);
                baos.write(i2);
            } else {
                baos.write(i1);
                baos.write(i2);
                baos.write((Base64EncodeChars.indexOf(src.charAt(i + 2)) << 6) | (Base64EncodeChars.indexOf(src.charAt(i + 3))));
            }
        }
        return baos.toByteArray();
    }
}
posted @ 2023-08-25 14:28  我不是萌新  阅读(85)  评论(0编辑  收藏  举报