定义
Base64是一种基于64个可打印字符来表示二进制数据的表示方法。由于2的6次方等于64,所以每6个位元为一个单元,对应某个可打印字符。三个字节有24个位元,对应于4个Base64单元,即3个字节需要用4个可打印字符来表示。它可用来作为电子邮件的传输编码。在Base64中的可打印字符包括字母A-Z、a-z、数字0-9 ,这样共有62个字符,此外两个可打印符号在不同的系统中而不同。一些如uuencode的其他编码方法,和之后binhex的版本使用不同的64字符集来代表6个二进制数字,但是它们不叫Base64。
Base64常用于在通常处理文本数据的场合,表示、传输、存储一些二进制>数据。包括MIME的email,email via MIME, 在XML中存储复杂数据.Base64编码是从二进制到字符的过程,可用于在HTTP环境下传递较长的标识信息。采用Base64编码具有不可读性,需要解码后才能阅读。
base64 编码表 索引表
维基百科中 的例子 查表 转换
维基百科中是这样 解释的
将String 转 成Base64 码
思路
- 建立 base64 码表 用char[]数组存取 用数组的优势: 下标就对应BASE64 的 索引 很方便
- 将字符串 转换成 byte 数组 (坑: 转换成char数组的话 就只能 转编译 字母和数值 因为 都是一个字节的 其他的都不行 特别是中文 在utf-8 是 3个字节 在gbk 是两个字节 这还只是 常用字 生僻字,表情 的字节更多了)
- 按照 base64 的规则 将8位对应为6位 原来的编码3个字节 3乘8位 base64码 4乘6位 我们可以将24 位作为一组 而int 有4个字节 32位 我们可以用int 去装
- 上面说了 可以将24位作为一组 对于原码 不一定会被8整除 在末尾我们可以 增加 8位 或 16 位 也就是1字节或2字节;
- 将int值查表 获得对应的字符 char[]
// 思路一
private static final char[] BASE64 = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', '+', '/'
};
//思路二
byte[] bytes = str.getBytes(StandardCharsets.UTF_8);
//思路四
if (bytes.length % 3 == 1) {
// 数组 扩容 增加两个字节 也就是16位
byte[] arr2 = Arrays.copyOf(bytes, bytes.length + 2);
if (bytes.length % 3 == 2) {
// 数组 扩容 增加一个字节 也就是8位
byte[] arr2 = Arrays.copyOf(bytes, bytes.length + 1);
//byte 数组扩容
private static char[] stringToBase64(String str) {
byte[] bytes = str.getBytes(StandardCharsets.UTF_8);
if (bytes.length % 3 == 1) {
// 数组
byte[] arr2 = Arrays.copyOf(bytes, bytes.length + 2);
char[] ppp = ppp(arr2);
ppp[ppp.length - 2] = '=';
ppp[ppp.length - 1] = '=';
return ppp;
}
if (bytes.length % 3 == 2) {
byte[] arr2 = Arrays.copyOf(bytes, bytes.length + 1);
char[] ppp = ppp(arr2);
ppp[ppp.length - 1] = '=';
return ppp;
}
char[] ppp = ppp(bytes);
return ppp;
}
//核心代码 将byte 先转成 int 也就是索引 在查表
public static char[] ppp(byte[] bytes) {
int k = 0;
int p = 0;
char[] oo = new char[bytes.length / 3 * 4];
while (k < oo.length) {
// int i = ((bytes[0] << 16) | (bytes[1] << 8) | (bytes[2]));
int i = (((bytes[p] & 0xFF) << 16) |
((bytes[p + 1] & 0xFF) << 8) |
(bytes[p + 2] & 0xFF));
int d3 = i & 0x3F;
int d2 = i >>> 6 & 0x3F;
int d1 = i >>> 12 & 0x3F;
int d0 = i >>> 18 & 0x3F;
oo[k] = BASE64[d0];
oo[k + 1] = BASE64[d1];
oo[k + 2] = BASE64[d2];
oo[k + 3] = BASE64[d3];
p = p + 3;
k = k + 4;
}
return oo;
}
将utf-8码 转成 base64 码 完整源代码
public class base2 {
private static final char[] BASE64 = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', '+', '/'
};
public static void main(String[] args) {
String a = "测试卡次数45";
char[] chars = stringToBase64(a);
String s = String.valueOf(chars);
System.out.println(s);
//下面是将base64码转成 utf-8 码的
// byte[] bytes = baseToString(s);
// String s1 = new String(bytes, StandardCharsets.UTF_8);
// System.out.println(s1);
//
// char[] chars1 = baseToString(s);
// String s1 = String.valueOf(chars1);
//
// System.out.println(s1);
}
/**
* 将转成 base64编码 返回 字符数组
*
* @param str 正常字符串
* @return
*/
private static char[] stringToBase64(String str) {
byte[] bytes = str.getBytes(StandardCharsets.UTF_8);
if (bytes.length % 3 == 1) {
// 数组
byte[] arr2 = Arrays.copyOf(bytes, bytes.length + 2);
char[] ppp = ppp(arr2);
ppp[ppp.length - 2] = '=';
ppp[ppp.length - 1] = '=';
return ppp;
}
if (bytes.length % 3 == 2) {
byte[] arr2 = Arrays.copyOf(bytes, bytes.length + 1);
char[] ppp = ppp(arr2);
ppp[ppp.length - 1] = '=';
return ppp;
}
char[] ppp = ppp(bytes);
return ppp;
}
public static char[] ppp(byte[] bytes) {
int k = 0;
int p = 0;
char[] oo = new char[bytes.length / 3 * 4];
while (k < oo.length) {
// int i = ((bytes[0] << 16) | (bytes[1] << 8) | (bytes[2]));
int i = (((bytes[p] & 0xFF) << 16) |
((bytes[p + 1] & 0xFF) << 8) |
(bytes[p + 2] & 0xFF));
int d3 = i & 0x3F;
int d2 = i >>> 6 & 0x3F;
int d1 = i >>> 12 & 0x3F;
int d0 = i >>> 18 & 0x3F;
oo[k] = BASE64[d0];
oo[k + 1] = BASE64[d1];
oo[k + 2] = BASE64[d2];
oo[k + 3] = BASE64[d3];
p = p + 3;
k = k + 4;
}
return oo;
}
}
将base64 码 转回 utf-8 码
逆向思路
源代码
public static byte[] baseToString(String base64) {
char[] chars = base64.toCharArray();
byte[] bytes = new byte[(base64.length() / 4 * 3)];
int bytesI = 0;
int d0 = 0;
int d1 = 0;
int d2 = 0;
int d3 = 0;
for (int i = 0; i < chars.length; i += 4) {
for (int j = 0; j < 64; j++) {
if (chars[i] == BASE64[j]) d0 = j;
if (chars[i + 1] == BASE64[j]) d1 = j;
if (chars[i + 2] == BASE64[j]) d2 = j;
if (chars[i + 3] == BASE64[j]) d3 = j;
}
int v = d3 | d2 << 6 | d1 << 12 | d0 << 18;
bytes[bytesI] = (byte) (v >> 16 & 0xFF);
// if (!(ys == 2 && (i == chars.length - 1)))
bytes[bytesI + 1] = (byte) (v >> 8 & 0xFF);
// if (!(ys >= 1 && (i == chars.length - 1)))
bytes[bytesI + 2] = (byte) (v & 0xFF);
bytesI += 3;
}
if (chars[chars.length - 1] == '=') {
if (chars[chars.length - 2] == '=') {
byte[] bytes1 = new byte[bytes.length - 2];
for (int i = 0; i < bytes1.length; i++) {
bytes1[i] = bytes[i];
}
return bytes1;
}
byte[] bytes1 = new byte[bytes.length - 1];
for (int i = 0; i < bytes1.length; i++) {
bytes1[i] = bytes[i];
}
return bytes1;
}
return bytes;
}
维基百科链接 BASE64
总结: base64 码现在的网络传输 用它的情况 非常多 像图片 音频 流媒体; 对于我来说 让我了解了编码的一些规则 是怎么编码的
有什么问题可以私聊我