一、主要目的
用Java语言开发一个自己的Base64的转换工具类。
二、主要难点
1、需要熟悉Base64的具体格式;
2、需要熟悉Java的语法;
三、主要代码如下
(一)定义工具类
public class Base64Util {
/**
* 将字节数据转成Base64字符串
* @param data 原始字节数组
* @return 编码后的字符串
*/
public static String toBase64(byte[] data) {
// 定义偏移量变量
int offset = 0;
// 定义存放结果的字符缓冲对象
StringBuffer result = new StringBuffer();
int b1 = 0;
int b2 = 0;
int b3 = 0;
int b4 = 0;
if (data != null) {
for (; offset + 2 < data.length; offset = offset + 3) {
// 把连续的4个字节放入一个int整型数中
int unit = 0;
int temp = 0;
unit = (data[offset] & 0xFF);
// 左移16位
unit = unit << 16;
temp = temp | unit;
unit = 0;
unit = (data[offset + 1] & 0xFF);
// 左移8位
unit = unit << 8;
temp = temp | unit;
unit = 0;
unit = data[offset + 2] & 0xFF;
temp = temp | unit;
b1 = temp & 0xFC0000;
result.append(mapToChar(b1 >> 18));
b2 = temp & 0x3F000;
result.append(mapToChar(b2 >> 12));
b3 = temp & 0xFC0;
result.append(mapToChar(b3 >> 6));
b4 = temp & 0x3F;
result.append(mapToChar(b4));
}
// 处理剩余的不能组成3个字节的数据
if (offset < data.length) {
int diff = 3 - (data.length - offset);
if (diff == 2){
int tail = 0;
int temp = 0;
tail = (data[offset] & 0xFF);
// 左移16位
tail = tail << 16;
temp = temp | tail;
b1 = temp & 0xFC0000;
result.append(mapToChar(b1 >> 18));
b2 = temp & 0x3F000;
result.append(mapToChar(b2 >> 12));
// 差两个就打印两个等号
result.append("==");
}
if (diff == 1){
int integrity = 0;
int temp = 0;
integrity = (data[offset] & 0xFF);
// 左移16位
integrity = integrity << 16;
temp = temp | integrity;
integrity = 0;
integrity = (data[offset + 1] & 0xFF);
// 左移8位
integrity = integrity << 8;
temp = temp | integrity;
b1 = temp & 0xFC0000;
result.append(mapToChar(b1 >> 18));
b2 = temp & 0x3F000;
result.append(mapToChar(b2 >> 12));
b3 = temp & 0xFC0;
result.append(mapToChar(b3 >> 6));
// 差一个就添加一个等号
result.append("=");
}
}
}
// 返回结果
return result.toString();
}
/**
* 将Base64编码字符串转成字节数组
* @param base64 base64编码的字符串
* @return 字节数组
*/
public static byte[] toData(String base64){
byte[] data = null;
if (base64 != null) {
// 3个字节为一组,转成4个字节
data = new byte[(base64.length() / 4) * 3 - count(base64, '=')];
byte temp1 = 0;
// 定义一个单元
int unit = 0;
int index = -1;
// 4个字符为一组
for (int offset = 0; offset < base64.length(); offset = offset + 4) {
// 归0
unit = 0;
temp1 = mapToByte(base64.charAt(offset));
unit = unit | ((0xFF & temp1) << 24);
temp1 = mapToByte(base64.charAt(offset + 1));
unit = unit | ((0xFF & temp1) << 16);
temp1 = mapToByte(base64.charAt(offset + 2));
unit = unit | ((0xFF & temp1) << 8);
temp1 = mapToByte(base64.charAt(offset + 3));
unit = unit | (0xFF & temp1);
// 开始取值
int b1 = ((unit & 0x3F000000) << 2) | ((unit & 0x300000) << 4);
index = index + 1;
data[index] = (byte) ((b1 >> 24) & 0xFF);
int b2 = ((unit & 0x0F0000) << 4) | ((unit & 0x003C00) << 6);
// 如果不等于符号=
if (base64.charAt(offset + 2) != '='){
index = index + 1;
data[index] = (byte) ((b2 >> 16) & 0xFF);
}
int b3 = ((unit & 0x0300) >> 2) | (unit & 0x3F);
// 如果不等于符号=
if (base64.charAt(offset + 3) != '=') {
index = index + 1;
data[index] = (byte) (b3 & 0xFF);
}
}
}
return data;
}
/**
* 查找字符串中某个字符的个数
* @param base64 字符串
* @param target 查找的数量
* @return
*/
private static int count(String base64, char target) {
int len = base64.length();
// 记录个数
int sum = 0;
for (int i = 0; i < len; i++) {
if (target == base64.charAt(i)){
sum = sum + 1;
}
}
return sum;
}
/**
* 用数值和字符进行替换的方法
* @param digit 数字
* @return 字符
*/
private static char mapToChar(int digit) {
// 返回大小字母
if (digit >= 0 && digit <= 25) {
// 数值为0是字母A
char temp = 'A';
// 相加差值后,转成字符
temp = (char) (temp + (digit - 0));
return temp;
}
// 转换小写字母
if (digit >= 26 && digit <= 51) {
// 数值为26,是字母a
char temp = 'a';
temp = (char) (temp + (digit - 26));
return temp;
}
// 转成数字
if (digit >= 52 && digit <= 61){
char t = '0';
t = (char) (t + (digit - 52));
return t;
}
// 转成其他字符
if (digit == 62) {
return '+';
}
if (digit == 63) {
return '-';
}
return '\0';
}
/**
* 进行Base64的字母和字符的替换
* @param c
* @return
*/
private static byte mapToByte(char c) {
byte data = 0;
if (c >= 'A' && c <= 'Z') {
data = (byte) (c - 'A' + 0);
}
if (c >= 'a' && c <= 'z') {
data = (byte) (c - 'a' + 26);
}
if (c >= '0' && c <= '9') {
data = (byte) (c - '0' + 52);
}
if (c == '+') {
data = 62;
}
if (c == '-') {
data = 63;
}
if (c == '='){
data = 0;
}
return data;
}
}
(二)定义测试类
public class Test{
public static void main(String[] args) {
String base1 = Base64Util.toBase64("hello world".getBytes());
String base2 = Base64Util.toBase64("你好,小明".getBytes());
System.out.println("base1: " + base1);
System.out.println("base2: " + base2);
System.out.println("base1解码结果:" + new String(Base64Util.toData(base1)));
System.out.println("base2解码结果:" + new String(Base64Util.toData(base2)));
}
}
四、运行结果如图
五、总结
1、基本满足字节数组和Base64字符串的转换;
2、主要缺点是只能单次转换,不能大容量分批次进行转换;内部没有很大的缓冲空间;
3、改进:设置内部的大容量缓冲空间,可以写入部分数据,判断是否能获取部分转换结果;如果写入结束,需要主动调用end(),返回最终的转换结果。(类似缓冲输出流)