數據的編碼(2)之BASE64編碼

最近研究一下編碼問題,base64編碼在項目中也是經常用到的。下面簡單介紹一下base64編碼。base64相當於64進制,它是由26個大寫字母,26個小寫字母和0-9、+ 、/的字符組成,其中A代表0, a代表26,0代表52,/代表63.base64編碼的原理:將3字節轉成4個字符3個字節 = 24bits ,將24個bits分爲4組,每組6bits,將每組用一個64進制的字符表示。base64不是加密算法,只是一種數據轉換算法。與十六進制相比,base64編碼長度較短。但是其缺點是不直觀,輸出的字符存在特殊符號。

下面用代碼實現base64編碼:

#include <stdio.h>
char base64_table[64];//64進制查詢表
char revers_table[128];//反向查詢表
void initBase64_table()
{
	int i;
	for (i = 0; i < 26; i++) base64_table[i] = 'A' + i;
	for (i = 0; i < 26; i++) base64_table[i + 26] = 'a' + i;
	for (i = 0; i < 10; i++) base64_table[i + 52] = '0' + i;
	base64_table[62] = '+';
	base64_table[63] = '/';

	//初始化反向查詢表
	for (i = 0; i < 128; i++) revers_table[i] = 0;
	for (i = 'A'; i <= 'Z'; i++) revers_table[i] = i - 'A';
	for (i = 'a'; i <= 'z'; i++) revers_table[i] = i - 'a' + 26;
	for (i = '0'; i <= '9'; i++) revers_table[i] = i - '0' + 52;
	revers_table['+'] = 62;
	revers_table['/'] = 63;
	revers_table['='] = 0;
}
int EncodeSize(int data_size)
{
	int groups = data_size / 3;
	if (data_size % 3)
		groups += 1;
	return groups * 4 + 1;
}
//剛好三個字節時
void Encode(const unsigned char* data , char* AdBase64str)
{
	//取高6位
	unsigned char p0 = (data[0] >> 2);
	//data[0]的低2位,data[1]的高4位
	unsigned char p1 = ((data[0] & 0x03) << 4) + (data[1] >> 4);
	//data[1]低4位,data[2]高3位
	unsigned char p2 = ((data[1] & 0x0f) << 2) + (data[2] >> 6);
	//data[2]低4位
	unsigned char p3 = data[2] & 0x3f;
	AdBase64str[0] = base64_table[p0];
	AdBase64str[1] = base64_table[p1];
	AdBase64str[2] = base64_table[p2];
	AdBase64str[3] = base64_table[p3];
}

//剛好是三個字節時的編碼
void Decode(unsigned char* data , const char* base64str)
{
	unsigned char p0, p1, p2, p3;
	p0 = revers_table[base64str[0]];
	p1 = revers_table[base64str[1]];
	p2 = revers_table[base64str[2]];
	p3 = revers_table[base64str[3]];

	data[0] = (p0 << 2) + (p1 >> 4);
	data[1] = (p1 << 4) + (p2 >> 2);
	data[2] = (p2 << 6) + p3;
}
//解碼需要的長度
int Decode_size(int str_size)
{
	int groups = str_size / 4;
	if (str_size % 4) return -1;//字符長度不是4的整數倍
	return groups * 3;
}
//通用的編碼
int Encode(const unsigned char* data, int data_size, char* base64str)
{
	int groups = data_size / 3;//整除組
	int remain = data_size % 3;//剩下的

	const unsigned char* inbuf = data;
	char* outbuf = base64str;
	//處理整除部分
	for (int i = 0; i < groups; i++)
	{
		Encode(inbuf, outbuf);
		inbuf += 3;
		outbuf += 4;
	}
	//處理剩餘的部分
	if (remain == 1)
	{
		Encode(inbuf, outbuf);
		groups += 1;
		outbuf[2] = outbuf[3] = '=';//加個等號
	}
	if (remain == 2)
	{
		unsigned char t[3] = { inbuf[0], inbuf[1], 0 };
		Encode(inbuf, outbuf);
		groups += 1;
		outbuf[3] = '=';
	}
	int str_size = groups * 4;
	//添加結束符
	base64str[str_size] = 0;
	return str_size;
}
//通用解析
int Decode(unsigned char* data , const char* base64str , int str_size)
{
	int groups = str_size / 4;//整除的
	const char* inbuf = base64str;
	unsigned char* outbuf = data;
	//處理整除的部分
	for (int i = 0; i < groups; i++)
	{
		Decode(outbuf, inbuf);
		inbuf += 4;
		outbuf += 3;
	}
	int data_size = groups * 3;
	outbuf -= data_size;
	//末尾2個等號
	if (base64str[str_size - 1] == '=' && base64str[str_size - 2] == '=')
	{
		data_size -= 2;
	}
	if (base64str[str_size - 1] == '=' && base64str[str_size - 2] != '=')
	{
		data_size -= 1;
	}
	outbuf[data_size] = 0;
	return data_size;
}
int main()
{
	initBase64_table();
	unsigned char data[] = { 0x4D, 0x5A, 0x90 , 0x6A , 0x7A};
	char base64Str[128];
	int n = Encode(data, 5 , base64Str);
	char* base64 = "TVqQas==";
	unsigned char data1[128];
	int n1 = Decode(data1, base64 , 8);

	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章