base64编码

base64编码,用于把任意8位字符变成可打印字符,用于文本传输

比如,json只能传输文本,如果需要传输二进制文件(比如图片),就可以用base64编码后传输

 

标准一个base64编码的64个可打印字符为

const char *base64char = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

原理是一个每三个字节,转换成4个字节,转换规则如下

原始数据         1101 0101        1000 0110        0010 1101

Base64              0011 0101        0001 1000        0001 1000        00101101

三个8位,总共24位,每6位作为一个新8位数的后6位,拼成24位,这样拼得的4个新8位数,分别作为base64char的下标,取得4个可打印字符。比如 hel,经过base64编码,就变成了 aGVs

如果不够3位,转换规则如下

原始数据         1101 0101        1000 0110       

Base64              0011 0101        0001 1000        0001 1000(不够,就补0)

凑不够4字节,第四个8位也不用作为下标了,直接补‘=’,helo,经过编码就变成了  aGVsbw==

 

解码的话,反过来就是,就不多说了

具体实现网上很多,这里放一个

char *base64_encode_file(const char *infile, int *outlen)
{	
	FILE *fp = NULL;
	unsigned int fileSize = 0;
	char *fileData = NULL;
    char *fileBase64 = NULL;
	size_t ret = 0;
	unsigned int base64_len;

	fp = fopen(infile,"rb");
	if (NULL == fp)
    {
	    printf("file open file\n");
		goto failed;
    }

	fseek(fp, 0L, SEEK_END);
	fileSize = ftell(fp);
	fseek(fp, 0L, SEEK_SET);
 
    printf("file length :%d\n", fileSize);
	fileData= (char *)malloc(sizeof(char)*fileSize);
	if (NULL == fileData)
    {
	    printf("malloc failed\n");
		goto failed;
    }
 
	ret = fread(fileData, 1, fileSize, fp);
	 if (ret != fileSize)  
    {  
        printf("file read failed\n");  
		goto failed;
    }  
    fclose(fp);
    
	fileBase64= (char *)malloc(sizeof(char) * fileSize * 2);
	if (NULL == fileBase64)
    {
	    printf("malloc failed\n");
		goto failed;
    }

    base64_encode((unsigned char*)fileData, fileBase64, fileSize);

    base64_len = strlen(fileBase64);
    printf("base64 str length:%d\n", base64_len);
	printf("%s\n", fileBase64);

	*outlen = base64_len;
	free(fileData);
	return fileBase64;

failed:
	if(fp)	fclose(fp);
	if(fileData)	free(fileData);
	return NULL;
}

 
int base64_decode_file(char *base64_data, int len, char *outfile)
{
	FILE *fp = NULL;
	int decoded_len;
    char *decoded_data = NULL;
	decoded_data= (char *)malloc(len * 3 / 4);	//	解码后长度为原数据的3/4
	if (NULL == decoded_data)
    {
	    printf("malloc failed");
	   	return -1;
    }
    decoded_len = base64_decode(base64_data, len, (unsigned char*)decoded_data);

	fp = fopen(outfile,"wb");   
	if (NULL == fp)
    {
	    printf("file open file");
		return -1;
    }
	printf("decoded_len=[%d]\n", decoded_len);
    fwrite(decoded_data, 1, decoded_len, fp);
    fclose(fp);

	free(decoded_data);

	return 0;
}

const char * base64char = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
int base64_encode( const unsigned char * orig_data, char * base64, int length )
{
    int i, j;
    unsigned char current;
 
    for ( i = 0, j = 0 ; i < length ; i += 3 )
    {
    	//	取了第一个8位的前6位
        current = (orig_data[i] >> 2) ;
        current &= (unsigned char)0x3F;
        base64[j++] = base64char[(int)current];
 
 	//	取了第一个8位的后2位
        current = ( (unsigned char)(orig_data[i] << 4 ) ) & ( (unsigned char)0x30 ) ;
        if ( i + 1 >= length )
        {
            base64[j++] = base64char[(int)current];
            base64[j++] = '=';
            base64[j++] = '=';
            break;
        }
	//	取了第二个8位的前4位,与前面2位组成6位
        current |= ( (unsigned char)(orig_data[i+1] >> 4) ) & ( (unsigned char) 0x0F );
        base64[j++] = base64char[(int)current];
 
 	//	取了第二个8位的后4位
        current = ( (unsigned char)(orig_data[i+1] << 2) ) & ( (unsigned char)0x3C ) ;
        if ( i + 2 >= length )
        {
            base64[j++] = base64char[(int)current];
            base64[j++] = '=';
            break;
        }
	//	取了第三个8位的前2位,与前面4位组成6位
        current |= ( (unsigned char)(orig_data[i+2] >> 6) ) & ( (unsigned char) 0x03 );
        base64[j++] = base64char[(int)current];
 
 	//	取了第三个8位的后6位
        current = ( (unsigned char)orig_data[i+2] ) & ( (unsigned char)0x3F ) ;
        base64[j++] = base64char[(int)current];
    }
    base64[j] = '\0';
    return 0;
}
 
 //	return	decoded data length
int base64_decode( const char * base64, int len, unsigned char * decoded_data )
{
    int i, j;
    unsigned char k;
    unsigned char temp[4];
    int do_len = len <= strlen(base64) ? len : (int)strlen(base64);
    for ( i = 0, j = 0; i < do_len ; i += 4 )
    {
        memset( temp, 0xFF, sizeof(temp) );
        for ( k = 0 ; k < 64 ; k ++ )
        {
            if ( base64char[k] == base64[i] )
                temp[0]= k;
        }
        for ( k = 0 ; k < 64 ; k ++ )
        {
            if ( base64char[k] == base64[i+1] )
                temp[1]= k;
        }
        for ( k = 0 ; k < 64 ; k ++ )
        {
            if ( base64char[k] == base64[i+2] )
                temp[2]= k;
        }
        for ( k = 0 ; k < 64 ; k ++ )
        {
            if ( base64char[k] == base64[i+3] )
                temp[3]= k;
        }
 
 	//	取第一个6位与第二个6位的前2位,组成8位
        decoded_data[j++] = ((unsigned char)(((unsigned char)(temp[0] << 2))&0xFC)) |
                ((unsigned char)((unsigned char)(temp[1]>>4)&0x03));
        if ( base64[i+2] == '=' )
            break;
 
 	//	取第二个6位的后4位与第三个6位的前4位,组成8位
        decoded_data[j++] = ((unsigned char)(((unsigned char)(temp[1] << 4))&0xF0)) |
                ((unsigned char)((unsigned char)(temp[2]>>2)&0x0F));
        if ( base64[i+3] == '=' )
            break;
 
 	//	取第三个6位的后2位与第四个6位的6位,组成8位
        decoded_data[j++] = ((unsigned char)(((unsigned char)(temp[2] << 6))&0xF0)) |
                ((unsigned char)(temp[3]&0x3F));
    }
    return j;
}

int main()
{
	int len;
/*
	char *str = "AAAAAAAAAA";
	char str_encode[1024] = "";
	base64_encode( (unsigned char*)str, str_encode, strlen(str));

	printf("orignal str=[%s]\n", str);
	printf("encode str=[%s]\n", str_encode);
*/
	char *data = base64_encode_file("screen.jpg", &len);
	if(!data)
		printf("base64_encode_file error\n");
	base64_decode_file(data, len, "a.jpg");
	free(data);

	return 0;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值