Base64 编解码的C语言实现
来源:互联网 发布:文华财经期货 for mac 编辑:程序博客网 时间:2024/05/19 16:35
简介
Base64编码是将任何类型的数据转换成ASCII码的可见字符,然后接收端再反向解码,得到原始的数据。最早的的Base是用于发送Email内容的。
经过Base64转换之后的数据大小变大了,为原数据的4/3大小。但是方便了传输,比如由于base64的编码中没有<>等特殊字符,可以不用转义扫描,直接放在XML中,放在MIME中,甚至直接不经过转义扫描存进数据库中。由于有这些方便的特性,即使数据量变大,base64编码还是被广泛使用。
原理
编码原理
每个字节8位,每次取出3个字节,也就是3 x 8 = 24 位。然后每次从此24位中取出6位,然后在前端补2位0,组成新的8位,也就是一个字节。这样就将3个字节转换成了4个字节。由于前面两位都是0,所以转换后的每个字节能表示的最大数字为63, 也就是说转换后的每个字节只可能是0-63中的一个数字。
然后根据规范给出的Base64索引表,将1-63 这64个数字转换成"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"中的一个。
当最后取出3个字节不够时,不够的位置补0,并且最后少一个字节时编码的最后加一个“=”,少两个字节时加两个"="
解码原理
解码是编码的反向过程,每次取出4个字节,然后将每个字节的字符转换成原始Base64索引表对应的索引数字,也就是编码时3字节转换成4字节的转换结果。然后使用位操作将每字节前2位去掉,重新转换成3字节。需要注意的是最后对于结尾“=”的处理。
代码实现
ENCODE:
static char base64_index[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; char *base64_encode(const char *input, const size_t length, char *output){ *output = '\0'; if (input == NULL || length < 1) return output; char *p = (char*)input; char *p_dst = (char*)output;; char *p_end = (char*)input + length; int loop_count = 0; // 0x30 -> 00110000 // 0x3C -> 00111100 // 0x3F -> 00111111 while (p_end - p >= 3) { *p_dst++ = base64_index[( p[0] >> 2 )]; *p_dst++ = base64_index[( (p[0] << 4) & 0x30 ) | ( p[1] >> 4 )]; *p_dst++ = base64_index[( (p[1] << 2) & 0x3C ) | ( p[2] >> 6 )]; *p_dst++ = base64_index[p[2] & 0x3F]; p += 3; } if (p_end - p > 0) { *p_dst++ = base64_index[(p[0] >> 2)]; if (p_end - p == 2) { *p_dst++ = base64_index[( (p[0] << 4) & 0x30 ) | ( p[1] >> 4 )]; *p_dst++ = base64_index[(p[1] << 2) & 0x3C]; *p_dst++ = '='; } else if (p_end - p == 1) { *p_dst++ = base64_index[(p[1] << 4) & 0x30]; *p_dst++ = '='; *p_dst++ = '='; } } *p_dst = '\0'; return output;}
DECODE:
// 16 * 16static int base64_decode_map[256] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0 - 15 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 16 - 31 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, // 32 - 47 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, // 48 - 63 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 64 - 79 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, // 80 - 95 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 96 - 111 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, // 112 - 127 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 128 - 143 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 144 - 159 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 160 - 175 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 176 - 191 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 192 - 207 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 208 - 223 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 224 - 239 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 240 - 255};char *base64_decode(const char* input, char *output){ output[0] = '\0'; if (input == NULL || output == NULL) return output; int input_len = strlen(input); if (input_len < 4 || input_len % 4 != 0) return output; // 0xFC -> 11111100 // 0x03 -> 00000011 // 0xF0 -> 11110000 // 0x0F -> 00001111 // 0xC0 -> 11000000 char *p = (char*)input; char *p_out = output; char *p_end = (char*)input + input_len; for (; p < p_end; p += 4) { *p_out++ = ((base64_decode_map[p[0]] << 2) & 0xFC) | ((base64_decode_map[p[1]] >> 4) & 0x03); *p_out++ = ((base64_decode_map[p[1]] << 4) & 0xF0) | ((base64_decode_map[p[2]] >> 2) & 0x0F); *p_out++ = ((base64_decode_map[p[2]] << 6) & 0xC0) | (base64_decode_map[p[3]]); } if (*(input + input_len - 2) == '=') { *(p_out - 2) = '\0'; } else if (*(input + input_len - 1) == '=') { *(p_out - 1) = '\0'; } return output;}
代码中的base64_decode_map的作用就是将base64索引中的ASCII字符转换成原始的0-63的数字。
其他
base64在不同的场景也有一个差别,有的编码结果中每76个字符加入一个换行。这也是正确的。以上的代码示例中没有加入,如需加入只需计数,定期加入换行符即可。
编码结果的大小在不加入换行符时是原来长度的4/3,但是需要注意精确malloc内存时,需要 (org_len + 3) * 4 / 3,如果需要增加结尾的'\0',需要再加1位。或者直接org_len *4 / 3 + 2
- Base64 编解码的C语言实现
- Base64编解码的C语言实现
- Base64 编解码C语言实现
- Base64 编解码C语言实现
- C语言实现Base64编解码
- C语言实现base64编解码
- Base64 编解码C语言实现
- Base64 编解码C语言实现
- Base64 编解码C语言实现
- Base64 编解码C语言实现
- openssl 中base64编解码的c语言实现
- C语言base64编解码
- base64编解码 C语言源码
- Base64 编解码C语言版本
- JavaScript 语言 Base64 编解码实现类
- base64编码解码的实现(C语言)
- base64编码解码的实现(C语言)
- Base64编码解码的实现(C语言)
- 交叉编译alsa-lib
- 鸡兔同笼
- 门径管理系统
- 实现正则表达式的.和*
- 给一个不多于5位的正整数,要求:(1)求它是几位数,(2)逆序打印出各位数字。
- Base64 编解码的C语言实现
- sqlite第三方类库:FMDB使用
- UVALive 5006 (BFS+heap+01背包)
- 关于android 4.2版本的sdcard文件目录分析(含修正)
- 有n个整数,使其前面各数顺序向后移m个位置,最后m个数变成最前面的m个数。
- Linux 文件权限
- 625这个数字很特别,625的平方等于390625,刚好其末3位是625本身。除了625,还有其它的3位数有这个特征吗?请编写程序,寻找所有这样的3位数:它的平方的末3位是这个数字本身。
- IPD流程概述
- Linux下解压命令