C++ Base64实现与JavaBase64互通

原理

ANSII—>Base64 : Base64_Encode

三个ANSII字符

3乘8=4乘6 思想
每个ANSII字符取值范围为 [0,128) 不超过8位字符
则每三个字符有24位对应的2进制 将这24位平均拆分4组 每组前边补00 得新串32位 平均分4份 得 小于64位的4个数对应
Base64解码表 ‘ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/’

例 “AAA” 转 Base64
A 的 ANSII码 为65 对应 2进制为 01000001
那么 AAA对应二进制010000010100000101000001
拆分4组 010000 010100 000101 000001
补00 得 00010000000101000000010100000001
再拆4份对应10进制 16 20 5 1
对应解码表 Q U F B

不足三位的情况处理

每次取前6位,不足则补零,对其到8的倍数。


“A” 转 Base64
A 对应2进制为 01000001
拆分补零 00010000 00010000
对应10进制 16 16
对应解码表 Q Q 补两个=
即: Q Q = =

“AA” 转 Base64
AA 对应 2进制为 0100000101000001
拆分补零 00010000 00010100 00000100
对应10进制 16 20 4
对应解码表 Q Q 补一个 =
即: Q U E =

Base64—>ANSII : Base64_Decode

同样检测=号的个数逆向转换 不做赘述

注意

没有引入其他库 仅有 bitset 用来将获取2进制表示 可自行实现
百度过C++版本 虽然可以搜到但实现好像是错的,特此贡献。
不保证代码一定没有BUG,主要传递的是思想。
转载请表明出处: https://blog.csdn.net/best335/article/details/89248692

#include<bitset>
#include<iostream>
typedef unsigned char byte;
const byte BASE64_STANDARD_ENCODE[] = { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" };
const byte BASE64_BIN[] = { 128,64,32,16,8,4,2,1 };


std::string ByteToBin8(byte aByte) {
	return std::bitset<8>(aByte).to_string();
}

byte Bin8ToByte(std::string aStr) {
	byte rByte = 0;
	for (int i = 0; i<8; ++i) if (aStr[i] == '1') rByte += BASE64_BIN[i];
	return rByte;
}

std::string Bin8ToBin6(std::string aStr) {
	return "00" + aStr.substr(0, 6) + "00" + aStr.substr(6, 6) + "00" + aStr.substr(12, 6) + "00" + aStr.substr(18, 6);
}

std::string Bin6ToBin8(std::string aStr) {
	return aStr.substr(2, 6) + aStr.substr(10, 6) + aStr.substr(18, 6) + aStr.substr(26, 6);
}

std::string Encode(std::string aStr, int Type) {
	std::string Bin6 = "";
	switch (Type) {
	case 1:
		Bin6 = "00" + ByteToBin8(aStr[0]).substr(0, 6) + "00" + ByteToBin8(aStr[0]).substr(6, 2) + "00000100000001000000";
		break;
	case 2:
		Bin6 = "00" + ByteToBin8(aStr[0]).substr(0, 6) + "00" + ByteToBin8(aStr[0]).substr(6, 2) + ByteToBin8(aStr[1]).substr(0, 4) + "00" + ByteToBin8(aStr[1]).substr(4, 4) + "0001000000";
		break;
	default:
		Bin6 = Bin8ToBin6(ByteToBin8(aStr[0]) + ByteToBin8(aStr[1]) + ByteToBin8(aStr[2]));
		break;
	}
	return  std::string(1, BASE64_STANDARD_ENCODE[Bin8ToByte(Bin6.substr(0, 8))]) +
		std::string(1, BASE64_STANDARD_ENCODE[Bin8ToByte(Bin6.substr(8, 8))]) +
		std::string(1, BASE64_STANDARD_ENCODE[Bin8ToByte(Bin6.substr(16, 8))]) +
		std::string(1, BASE64_STANDARD_ENCODE[Bin8ToByte(Bin6.substr(24, 8))]);
}

std::string Base64_Encode(std::string toEncode) {
	std::string rStr = "";
	for (int i = 0, ni = toEncode.size(); i < ni; i += 3) {
		switch (ni - i)
		{
		case 1:
			rStr += Encode(toEncode.substr(i, 1), 1);
			break;
		case 2:
			rStr += Encode(toEncode.substr(i, 2), 2);
			break;
		default:
			rStr += Encode(toEncode.substr(i, 3), 3);
			break;
		}
	}
	return rStr;
}
int findDict(byte b) {
	for (int i = 0; i<65; ++i)
		if (b == BASE64_STANDARD_ENCODE[i])
			return i;
	return -1;
}
std::string Decode(std::string aStr) {
	std::string Bin8 = ByteToBin8(findDict(aStr[0])) + ByteToBin8(findDict(aStr[1])) + ByteToBin8(findDict(aStr[2])) + ByteToBin8(findDict(aStr[3]));
	std::string rStr = "";
	if (Bin8[17] == '1') {
		Bin8 = Bin8.substr(2, 6) + Bin8.substr(10, 2);
		rStr = std::string(1, Bin8ToByte(Bin8));
	}
	else if (Bin8[25] == '1') {
		Bin8 = Bin8.substr(2, 6) + Bin8.substr(10, 6) + Bin8.substr(18, 4);
		rStr = std::string(1, Bin8ToByte(Bin8.substr(0, 8))) + std::string(1, Bin8ToByte(Bin8.substr(8, 8)));
	}
	else {
		Bin8 = Bin8.substr(2, 6) + Bin8.substr(10, 6) + Bin8.substr(18, 6) + Bin8.substr(26, 6);
		rStr = std::string(1, Bin8ToByte(Bin8.substr(0, 8))) + std::string(1, Bin8ToByte(Bin8.substr(8, 8))) + std::string(1, Bin8ToByte(Bin8.substr(16, 8)));
	}
	return rStr;
}
std::string Base64_Decode(std::string toDecode) {
	std::string rStr = "";
	for (int i = 0, ni = toDecode.size(); i < ni; i += 4) {
		rStr += Decode(toDecode.substr(i, 4));
	}
	return rStr;
}
调用
Base64_Encode("要加密的串");
Base64_Decode("已经经过Base64Encode的串");

校验
int main(){
	std::string f="";
	for(int i=1;i<256;++i)f+=char(i);
	cout<<f<<endl;
	cout<<Base64_Decode(Base64_Encode(f))<<endl;
	return 0;
}
//JAVA
public final class Base64 {
    final private static byte Base64_Encode_DataSet[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".getBytes();
    final private static int binValues[]= {-128,64,32,16,8,4,2,1,0};
    
    final private static String getBin8(byte i) {
    	String str=String.format("%8s", Integer.toBinaryString(i)).replace(' ', '0');
    	return str.substring(str.length()-8);
    }
    final private static byte getByte(String Bin8) {
    	byte rByte = 0;
    	for(int i=0;i<8;++i)if(Bin8.charAt(i)=='1')rByte+=binValues[i];
    	return rByte;
    }
    final private static String Bin8ToBin6(String aStr) {
    	return "00"+aStr.substring(0, 6)+"00"+aStr.substring(6, 12)+"00"+aStr.substring(12, 18)+"00"+aStr.substring(18, 24);
    }
    public final static String encode(String toEncode) {
    	return encode(toEncode.getBytes());
    }
    public final static String encode(byte[]toEncode) {  
    	String rStr = "";
    	int i=0,j=1,k=2,ni=toEncode.length,Round3 = ni%3;
    	String Bin6="";
    	for (ni=ni/3*3; i < ni; i += 3,j+=3,k+=3) {
    		Bin6 = Bin8ToBin6(getBin8(toEncode[i])+getBin8(toEncode[j])+getBin8(toEncode[k]));
    		rStr+=  new String( new byte[]{Base64_Encode_DataSet[getByte(Bin6.substring( 0,  8))],Base64_Encode_DataSet[getByte(Bin6.substring( 8, 16))],Base64_Encode_DataSet[getByte(Bin6.substring(16, 24))],Base64_Encode_DataSet[getByte(Bin6.substring(24, 32))]});
    	}
    	switch(Round3) {
    	case 1:
    		Bin6 = "00"+getBin8(toEncode[i]).substring(0,6)+"00"+getBin8(toEncode[i]).substring(6,8)+"00000100000001000000";
    		rStr+=  new String( new byte[]{Base64_Encode_DataSet[getByte(Bin6.substring( 0,  8))],Base64_Encode_DataSet[getByte(Bin6.substring( 8, 16))],Base64_Encode_DataSet[getByte(Bin6.substring(16, 24))],Base64_Encode_DataSet[getByte(Bin6.substring(24, 32))]});
        	break;
    	case 2:
    		Bin6 = "00"+getBin8(toEncode[i]).substring(0,6)+"00"+getBin8(toEncode[i]).substring(6,8)+getBin8(toEncode[j]).substring(0,4)+"00"+getBin8(toEncode[j]).substring(4,8)+ "0001000000";
    		rStr+=  new String( new byte[]{Base64_Encode_DataSet[getByte(Bin6.substring( 0,  8))],Base64_Encode_DataSet[getByte(Bin6.substring( 8, 16))],Base64_Encode_DataSet[getByte(Bin6.substring(16, 24))],Base64_Encode_DataSet[getByte(Bin6.substring(24, 32))]});
        	break;
    	}
    	return rStr;
    }
    final private static byte findDict(byte aByte) {
    	for (byte i=0;i<65;++i)
    		if(Base64_Encode_DataSet[i]==aByte)
    			return i;
    	return -1;
    }
    public final static byte[] decode(byte[] toDecode) {
    	return decode(new String(toDecode));
    }
    public final static byte[] decode(String toDecode) {
    	int i=0,ni=toDecode.length(),j=0;
    	byte rByte[]=new byte[toDecode.length()/4*3-(toDecode.charAt(ni-2)=='='?2:toDecode.charAt(ni-1)=='='?1:0)];
    	String Bin8="";
    	byte [] aByte;
    	for (ni-=4; i < ni; i += 4) {
    		aByte=toDecode.substring(i,i+4).getBytes();
        	Bin8=getBin8(findDict(aByte[0]))+getBin8(findDict(aByte[1]))+getBin8(findDict(aByte[2]))+getBin8(findDict(aByte[3]));
        	Bin8=Bin8.substring(2,8)+Bin8.substring(10,16)+Bin8.substring(18,24)+Bin8.substring(26,32);
        	rByte[j++]=getByte(Bin8.substring(0,8));
        	rByte[j++]=getByte(Bin8.substring(8,16));
        	rByte[j++]=getByte(Bin8.substring(16,24));
    	}
		aByte=toDecode.substring(i,i+4).getBytes();
    	Bin8=getBin8(findDict(aByte[0]))+getBin8(findDict(aByte[1]))+getBin8(findDict(aByte[2]))+getBin8(findDict(aByte[3]));
    	if(Bin8.charAt(17)=='1'){
    		rByte[j++]=getByte(Bin8.substring(2,8)+Bin8.substring(10,12));
    	}
    	else if(Bin8.charAt(25)=='1'){
    		Bin8=Bin8.substring(2,8)+Bin8.substring(10,16)+Bin8.substring(18,22);
    		rByte[j++]=getByte(Bin8.substring(0,8));
        	rByte[j++]=getByte(Bin8.substring(8,16));
    	}
    	else {
    		Bin8=Bin8.substring(2,8)+Bin8.substring(10,16)+Bin8.substring(18,24)+Bin8.substring(26,32);
    		rByte[j++]=getByte(Bin8.substring(0,8));
        	rByte[j++]=getByte(Bin8.substring(8,16));
        	rByte[j++]=getByte(Bin8.substring(16,24));
    	}
    	return rByte;
    }
}
//测试 java Base64
		byte f[]=new byte[256];
		for(int i=0;i<256;++i) f[i]=(byte) i;
		byte e[] = java.util.Base64.getEncoder().encode(f);//JDK1.8
		byte g[] = Base64.encode(f).getBytes();
		System.out.println(java.util.Base64.getEncoder().encodeToString(f));
		System.out.println(Base64.encode(f));
		System.out.println(Base64.encode(Base64.decode(java.util.Base64.getEncoder().encode(f))));
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值