【编码】Base64编码

简述

为什么叫Base64?个人理解是,基础的64个字符。
而它的作用?用基础的(可理解为可安全传输的)64个字符,来表示难以表示的二进制或对程序造成干扰的字符。

Base64的编码过程

自行编码分析Base64的编码方式

Base64的编码范围

import org.junit.Test;

public class Base64Map {
	
	public static char[] chars = new char[64];
	
	static {
		for (int i = 0; i < 26; i++) {
			chars[i] = (char)((int)'A' + i);
		}
		for (int i = 26; i < 52; i++) {
			chars[i] = (char)((int)'a' + i - 26);
		}
		for (int i = 52; i < 62; i++) {
			chars[i] = (char)((int)'0' + i - 52);
		}
		chars[62] = '+';
		chars[63] = '/';
	}
	
	/**
	 * 获取对应的Base64字符
	 * @param index 下标
	 * @return 对应的Base64字符
	 */
	public static char getBase64(int index) {
		return chars[index];
	}
	
	@Test
	public void printAll() {
		System.out.println(chars);
	}

}

即:

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/

简单的二进制工具

import org.junit.Test;

public class BinaryUtils {
	
	/**
	 * 将多个字节转换为能打印的位
	 * @param b 多个字节
	 * @return 能打印的位
	 */
	public static String bytes2Bit(byte[] bytes) {
		StringBuffer sb = new StringBuffer();
		for (byte b : bytes) {
			sb.append(BinaryUtils.byte2Bit(b));
		}
		return sb.toString();
	}

	/**
	 * 将字节转换为能打印的位
	 * @param b 字节
	 * @return 能打印的位
	 */
	public static String byte2Bit(byte b) {
		/* 备注:也可用JDK方法实现:Integer.toBinaryString() */
		
		StringBuffer sb = new StringBuffer();
		for (int i = 7; i >= 0; i--) { // 右移i位
			sb.append((byte) ((b >> i) & 1));
		}
		return sb.toString();
	}
	
	/**
	 * 二进制转换为十进制
	 * @param binary 二进制
	 * @return 十进制
	 */
	public static Integer binary2Decimal(String binary) {
		if (binary == null || binary.trim().length() == 0) {
			return null;
		}
		
		binary = binary.trim();
		char[] chars = binary.toCharArray();
		
		int sum = 0;
		for (int i = chars.length - 1; i >= 0; i--) {
			if (chars[i] == '0') {
				continue;
			}
			sum = sum + (int)Math.pow(2, chars.length - 1 - i);
		}
		return sum;
	}
	
	@Test
	public void bytes2BitTest() {
		System.out.println(BinaryUtils.bytes2Bit("hello".getBytes()));
	}
	
	@Test
	public void byte2BitTest() {
		System.out.println(BinaryUtils.byte2Bit("h".getBytes()[0]));
		System.out.println(Integer.toBinaryString("h".getBytes()[0]));
	}
	
	@Test
	public void binary2DecimalTest() {
		System.out.println(BinaryUtils.binary2Decimal("011010"));
	}

}

简单的编码过程


public class Base64Analyzer {

	public static void main(String[] args) {
		/* TODO
		 * 此为练习,部分逻辑未实现:
		 * 1、无考虑补位到6、8的公倍数情况;
		 * 2、无考虑6位全部为补位,编码为=的情况
		 */
		
		/* 转换为二进制 */
		String bitStr = BinaryUtils.bytes2Bit("hello".getBytes());
		System.out.println(bitStr);
		
		int bitSize = 6;
		String sixBitStr = null;
		Integer index = null;
		char base64Char;
		StringBuffer base64SB = new StringBuffer();
		for (int i = 0; i < bitStr.length(); i += 6) {
			/* 二进制按6位分组 */
			sixBitStr = bitStr.substring(i, i + 6 > bitStr.length() ? bitStr.length() : i + 6);
			if (sixBitStr.length() != 6) {
				sixBitStr = sixBitStr + String.format("%0" + (bitSize - sixBitStr.length()) + "d", 0); // 不足位后补0
			}
			
			// 将每6位的字符转换为十进制
			index = BinaryUtils.binary2Decimal(sixBitStr);
			
			// 根据下标获取对应的Base64字符
			base64Char = Base64Map.getBase64(index);
			System.out.println(sixBitStr + " -> " + base64Char);
			base64SB.append(base64Char);
		}
		
		System.out.println(base64SB.toString());
	}

}

日志:

0110100001100101011011000110110001101111
011010 -> a
000110 -> G
010101 -> V
101100 -> s
011011 -> b
000110 -> G
111100 -> 8
aGVsbG8

JDK转换Base64的方式

下例是JDK1.8的方法:

import java.util.Base64;

import org.junit.Test;

public class Base64Util {
	
	public static String encode(byte[] bytes) {
		return Base64.getEncoder().encodeToString(bytes);
	}
	
	public static byte[] decode(String s) {
		return Base64.getDecoder().decode(s);
	}
	
	@Test
	public void encodeTest() {
		System.out.println(Base64Util.encode("hello".getBytes()));
	}
	
	@Test
	public void decodeTest() {
		System.out.println(new String(Base64Util.decode("aGVsbG8=")));
	}

}

参考文章

让你完全理解base64是怎么回事

posted @   nick_huang  阅读(399)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· Ollama——大语言模型本地部署的极速利器
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· Windows编程----内核对象竟然如此简单?
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
点击右上角即可分享
微信分享提示