用于将字节进行base64编码或解码(C语言实现)

news/2024/10/2 16:19:24

V1.0 2024年6月13日 发布于博客园

目录
  • base64.h
  • base64.c

基本原理见代码注释!

base64.h

#ifndef _BASE64_H
#define _BASE64_H
/*** @file name : base64.h* @brief     : 用于将字节进行base64编码或解码* @author    : RISE_AND_GRIND@163.com* @date      : 2024年6月12日* @version   : 1.0* @note      :* CopyRight (c)  2023-2024   RISE_AND_GRIND@163.com   All Right Reseverd*//**Base64基本介绍*  什么是Base64编码?*      编码的主要目的是在需要通过文本传输或存储二进制数据的场景中,*      确保数据的完整性和可读性。直接使用ASCII存储二进制数据存在一些问题,*      因为二进制数据可能包含不可打印字符或特殊字符,这些字符在某些传输媒介(如电子邮件、URL等)中可能会被误解或破坏。*  为什么要使用Base64?*      可读性和可传输性:*          Base64编码将二进制数据转换为可打印的ASCII字符,确保数据在传输过程中不被改变。*          许多传输协议(如SMTP邮件协议)只支持文本数据,Base64编码使得二进制数据可以通过这些协议传输。**      避免数据损坏:*          某些传输通道可能会对非文本数据进行处理或修改,Base64编码可以避免这些问题。**      兼容性:*          Base64编码后的数据可以在不同系统和平台之间无缝传输,而不会受到字符集或编码方式的影响。**  Base64的应用:电子邮件附件、Web数据传输(图片、文件等)、数据存储(某些数据库)、加密和签名*//**Base64基本原理* Base64(64个字符) -->2^6即6个比特-->其字符编码范围为0~63* -->"A-Z" "a-z" "0~9" "+" "/"* -->'A-Z' -- 编码范围 0~25* -->'a-z' -- 编码范围 26~51* -->'0-9' -- 编码范围 52~61* -->'+'   -- 编码范围 62* -->'/'   -- 编码范围 63** 注意, 最后不足4字符会以'='补齐** 例如: 将ASCII码的"Man"转换为Base64编码为TWFu*  M---->ASCII对应值: A(65)+12 = 77  --->十六进制:0x4D--->二进制:0100 1101*  a---->ASCII对应值: a(97)+0  = 97  --->十六进制:0x61--->二进制:0110 0001*  n---->ASCII对应值: a(97)+13 = 110 --->十六进制:0x6E--->二进制:0110 1110**  在内存中(ASCII)        :0100 1101 0110 0001 0110 1110*  6位划分为Base64        :  010011|  010110|  000101|  101110*  但内存是以字节为单位    :00010011|00010110|00000101|00101110*  Base64显示             : T(19)   W(22)   F(5)     u(46)**  所以每3个字节ASCII码会生成4个字节的Base编码*/
/***************************************头文件***************************************/
#include <stdio.h>
#include <string.h>
/***************************************END******************************************/
// 查找Base64字符在表中的位置, 进行数值还原
int base64_char_value(char c);
/**将字符串进行Base64编码* @name      base64_encode* @brief     将字符串进行Base64编码* @param     input 输入的ASCII字符串* @param     output  得到的base64编码* @date      2024年6月12日* @version   1.0* @note*/
void base64_encode(const unsigned char *input, char *output);
/**将字符串进行Base64解码* @name      base64_decode* @brief     将字符串进行Base64解码* @param     input 输入的base64编码* @param     output  得到的ASCII字符串* @date      2024年6月12日* @version   1.0* @note*/
void base64_decode(const char *input, unsigned char *output);
#endif

base64.c

/*** @file name : base64.c* @brief     : 用于将字节进行base64编码或解码* @author    : RISE_AND_GRIND@163.com* @date      : 2024年6月12日* @version   : 1.0* @note      :* CopyRight (c)  2023-2024   RISE_AND_GRIND@163.com   All Right Reseverd*/#include "../../include/utilities/base64.h"// Base64字符表, 用于编码和解码 static限制为文件域
static const char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";// 查找Base64字符在表中的位置, 进行数值还原
int base64_char_value(char c)
{if (c >= 'A' && c <= 'Z') // 'A'到'Z'的值为0到25return c - 'A';if (c >= 'a' && c <= 'z') // 'a'到'z'的值为26到51return c - 'a' + 26;if (c >= '0' && c <= '9') // '0'到'9'的值为52到61return c - '0' + 52;if (c == '+') // '+'的值为62return 62;if (c == '/') // '/'的值为63return 63;return -1; // 非Base64字符返回-1
}/**将字符串进行Base64编码* @name      base64_encode* @brief     将字符串进行Base64编码* @param     input 输入的ASCII字符串* @param     output  得到的base64编码* @date      2024年6月12日* @version   1.0* @note*/
void base64_encode(const unsigned char *input, char *output)
{int length = strlen((const char *)input); // 计算输入字符串的长度int i = 0;                                // 计数器int j = 0;unsigned char a3[3] = {0}; // 每次输入3个ASCII码字节缓冲区, 3个ASCII码可生成4个Base64编码unsigned char a4[4] = {0}; // 每次输出4个Base64字符缓冲区while (length--) // 输入字符串的长度每次载入3个字节, 即长度每次-3{a3[i++] = *(input++); // 载入字符到输入数组中if (i == 3)           // 若输入了3个字符, 则触发编码{/**                           a3[0]     a3[1]     a3[2]*  在内存中(ASCII)        :0100 1101 0110 0001 0110 1110*  6位划分为Base64        :  010011|  010110|  000101|  101110*/a4[0] = (a3[0] & 0xfc) >> 2;                           // a3[0] & 11111100 取a3[0]的前6位a4[1] = ((a3[0] & 0x03) << 4) + ((a3[1] & 0xf0) >> 4); // 取a3[0]的后2位和a3[1]的前4位a4[2] = ((a3[1] & 0x0f) << 2) + ((a3[2] & 0xc0) >> 6); // 取a3[1]的后4位和a3[2]的前2位a4[3] = a3[2] & 0x3f;                                  // 取a3[2]的后6位for (i = 0; i < 4; i++) // 每次输出4个编码后的字符{*output++ = base64_table[a4[i]]; // 将编码后的Base64值映射到Base64字符表, 转换为ASCII码的形式显示(只是显示, 内容是Base64)}i = 0; // 重置计数器}}if (i) // 若位数不足3个字节{for (j = i; j < 3; j++) // 用0填充不足的字节部分{a3[j] = '\0';}// 同上操作a4[0] = (a3[0] & 0xfc) >> 2;a4[1] = ((a3[0] & 0x03) << 4) + ((a3[1] & 0xf0) >> 4);a4[2] = ((a3[1] & 0x0f) << 2) + ((a3[2] & 0xc0) >> 6);a4[3] = a3[2] & 0x3f;// 将已编码好的部分输出, +1是因为若只有一个字节也至少生成2个字符, 始终会+1for (j = 0; j < (i + 1); j++){*output++ = base64_table[a4[j]];}while ((i++ < 3)){*output++ = '='; // 用'='填充不足的部分并输出}}*output = '\0'; // 输出字符串完毕
}/**将字符串进行Base64解码* @name      base64_decode* @brief     将字符串进行Base64解码* @param     input 输入的base64编码* @param     output  得到的ASCII字符串* @date      2024年6月12日* @version   1.0* @note*/
void base64_decode(const char *input, unsigned char *output)
{int i = 0; // 计数器int j = 0;unsigned char a4[4] = {0}; // 每次输入4个Base64字符缓冲区unsigned char a3[3] = {0}; // 每次输出3个ASCII码字节缓冲区, 4个Base64编码可生成3个ASCII码while (*input){for (i = 0; i < 4; i++) // 以4个base字符为单位进行处理{if (*input == '=') // 若是末尾{a4[i] = 0; // 转换为'\0'}else // 若不是末尾{a4[i] = base64_char_value(*input);}input++; // 继续读入1个字符}a3[0] = (a4[0] << 2) + ((a4[1] & 0x30) >> 4);          // 解码第一个字节 取消移位a3[1] = ((a4[1] & 0x0f) << 4) + ((a4[2] & 0x3c) >> 2); // 解码第二个字节a3[2] = ((a4[2] & 0x03) << 6) + a4[3];                 // 解码第三个字节for (j = 0; j < 3; j++){*output++ = a3[j]; // 将解码后的字节写入输出}}*output = '\0'; // 结束字符串
}#if 0
int main()
{// 测试Base64编码const char *input_encode = "我爱中国"; // 正确值应该是"5oiR54ix5Lit5Zu9"char output_encode[50];                // 需要足够大的数组来存储Base64编码后的字符串base64_encode((const unsigned char *)input_encode, output_encode);printf("Base64 Encoded: %s\n", output_encode);// 测试Base64解码const char *input_decode = "6Zey5p2l5peg5LqL5pG46bG85pe2LCDlip7lhazlrqTlhoXmhI/mrLLnprvjgIIKIOaJi+aPoem8oOagh+i9u+i9u+a7kSwg55y86KeC5bGP5bmV5b+D6Ieq5Zek44CCCiDlkIzkuovlv5nnoozlv5nlvpfntK8sIOaIkeWNtOmXsumAuOW/g+asouWWnOOAggog5oyH5bCW6L275pWy6ZSu55uY5aOwLCDpsbzmuLjmsLTkuK3ku7vmhI/lrInjgIIKIOS4iuWPuOW/veeEtuS4tOaXtuiHsywg5oiR5YyG5b+Z5oqK6bG86JeP56We56eY44CCCiDpnaLlrrnkuKXogoPnnLzlpoLnlLUsIOe6teeEtuaIkeW/g+aFjOWmgum4oeOAggog5pil6aOO5ouC6Z2i5b+Y5Yqz6IumLCDor5fmhI/nm47nhLblv4PmrKLkuZDjgIIKIOS4gOeJh+i9u+advuWcqOW/g+WktCwg5pG46bG85Ly85LmO5peg56m35LmQ44CC";unsigned char output_decode[1024]; // 需要足够大的数组来存储解码后的数据base64_decode(input_decode, output_decode);printf("Base64 Decoded:\n %s\n", output_decode);return 0;
}
#endif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hjln.cn/news/44789.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

初始MyBatis ,详细步骤运行第一个MyBatis程序,同时对应步骤MyBatis底层剖析

1. 初始MyBatis ,详细步骤运行第一个MyBatis程序,同时对应步骤MyBatis底层剖析 @目录1. 初始MyBatis ,详细步骤运行第一个MyBatis程序,同时对应步骤MyBatis底层剖析每博一文案2. 前沿知识2.1 框架(framework)2.2 三层架构2.3 分析 JDBC 的缺点3. 初始了解MyBatis4. MyBat…

VSCode弹窗无法应用,终端无法键入命令行解决方法

1、VSCode弹窗无法应用 解决方式:卸载通义灵码插件 2.终端无法键入命令行 解决方式:取消兼容模式,添加设置

git提交代码步骤以及工作中常用的git命令

确保在开始这些步骤之前,你已经配置了 Git 用户信息(git config --global user.name "Your Name" 和 git config --global user.email "your.email@example.com"),并且已经克隆了远程仓库(git clone <repository-url>)。https://www.cnblogs.c…

快速识别你家的猫猫狗狗,教你用ModelBox开发AI萌宠应用

本文介绍了如何使用ModelBox开发一个动物目标检测的AI应用,从而掌握图片标注、数据处理和模型训练方法,以及对应的推理应用逻辑。本文分享自华为云社区《ModelBox-AI应用开发:动物目标检测【玩转华为云】》,作者:阳光大猫。 一、准备环境 ModelBox端云协同AI开发套件(Win…

Open WebUI

Open WebUI https://docs.openwebui.com/ ollama UI的独立演进版本。 不负责模型的部署。 可以对接 ollama后台 和 openai 接口。Open WebUI is an extensible, feature-rich, and user-friendly self-hosted WebUI designed to operate entirely offline. It supports various…

Console.log 美化

美化代码 // 美化打印实现方法 const prettyLog = () => {const isProduction = import.meta.env.MODE === "production";const isEmpty = (value: any) => {return value == null || value === undefined || value === "";};const prettyPrint = (t…

性能分析: 快速定位SQL问题

在数据库性能调优的实践中,SQL性能分析是至关重要的一环。一个执行效率低下的SQL语句可能会导致整个系统的性能瓶颈。 为了快速定位并解决这些问题,我们需要对SQL进行性能分析。本文将介绍一些常用的方法和技术,帮助大家快速定位SQL问题。 1、找出执行时间最长的SQL 首先,我…

IP地址按照数值大小进行排序

sort -n -t . -k1,1 -k2,2 -k3,3 -k4,4 ip.txt -n: 指示 sort 进行数值排序,而不是默认的字典序排序。 -t .: 设置字段的分隔符为点(.)。这通常用于处理IP地址或版本号等以点分隔的数值。 -k1,1 -k2,2 -k3,3 -k4,4: 这些是排序的关键部分,指定了排序的键。