【算法记录】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 @   我不是萌新  阅读(102)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示