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;
}