Base64 编解码
Base64编码简介
Base64用来将binary的字节序列数据编码成ASCII字符序列构成的文本。其使用的字符包括大小写字母各26个,加上10个数字,和加号“+”,斜杠“/”,一共64个字符。另外还使用等号“=”用来作为后缀。
Base64编码要求把3个8位字节(3*8=24)转化为4个6位的字节(4*6=24),之后在6位的前面补两个0,形成8位一个字节的形式。如果剩下的字符不足3个字节,则用0填充,最后的输出字符时使用'='作为结尾,因此编码后输出的文本末尾可能会出现1或2个'='。
为了保证所输出的编码字符都是可读的,Base64制定了一个编码表,以便进行统一转换。编码表的大小为2^6=64。
Base64编码表 码值 字符 码值 字符 码值 字符 码值 字符 0 A 16 Q 32 g 48 w 1 B 17 R 33 h 49 x 2 C 18 S 34 i 50 y 3 D 19 T 35 j 51 z 4 E 20 U 36 k 52 0 5 F 21 V 37 l 53 1 6 G 22 W 38 m 54 2 7 H 23 X 39 n 55 3 8 I 24 Y 40 o 56 4 9 J 25 Z 41 p 57 5 10 K 26 a 42 q 58 6 11 L 27 b 43 r 59 7 12 M 28 c 44 s 60 8 13 N 29 d 45 t 61 9 14 O 30 e 46 u 62 + 15 P 31 f 47 v 63 /
C++实现
#ifndef __BASE64_UTILS__ #define __BASE64_UTILS__#include <string>using std::string;class Base64Utils { public:Base64Utils(void);~Base64Utils(void);/** 将一个字节数组中的数据转为一个 base64 格式的数组*/static string Encode(const unsigned char* pEncodeData, int nLength);/** nLength 为 0 时返回需要 pOutBuffer 需要分配的大小; 否则解码数据, 并存入 pOutBuffer 指向的内存中. 返回值: 失败时返回0. 否则返回反解码后的字符的个数*/static int Decode(const string& strBase64, unsigned char* pOutBuffer, int nLength);/** 解析为一个字符串(由调用者确定解出的字符中不包含'\0'才能能调用此函数,否则返回的结果可能不是期望的值) */static string DecodeToString(const string& strBase64);/** 检查一个字符是否是 base64 编码的字符 */static bool CheckBase64(unsigned char bas64Char);protected:template <class T> static T min(T left, T right); };#endif __BASE64_UTILS__
#include "Base64Utils.h"// Base64 编码所用的字符, 其顺序由 base64 协议规定 static const string BASE64_ENCODE_TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";// 将 ascii 码表中, 对应的 Base64 字符的改成 Base64 字符表中的索引值, 以便解码时进行转行转换 static const unsigned char BASE64_DECODE_TABLE[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,62, // '+'0, 0, 0,63, // '/'52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // '0'-'9'0, 0, 0, 0, 0, 0, 0,0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // 'A'-'Z'0, 0, 0, 0, 0, 0,26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // 'a'-'z' };static const unsigned char BASE64_END_CHARACTER = '=';Base64Utils::Base64Utils(void) { }Base64Utils::~Base64Utils(void) { }template <class T> T Base64Utils::min(T left, T right) {return (left < right) ? left : right; }bool Base64Utils::CheckBase64(unsigned char bas64Char) {return (BASE64_ENCODE_TABLE.find(bas64Char) != -1) ? true : false; }string Base64Utils::Encode(const unsigned char* pEncodeData, int nLength) {string strBase64;int i = 0;for (; i + 2 < nLength; i += 3){strBase64.push_back(BASE64_ENCODE_TABLE.at((pEncodeData[i] >> 2) & 0x3f));strBase64.push_back(BASE64_ENCODE_TABLE.at(((pEncodeData[i] & 0x03) << 4) | ((pEncodeData[i + 1] >> 4) & 0x0f)));strBase64.push_back(BASE64_ENCODE_TABLE.at(((pEncodeData[i + 1] & 0x0f) << 2) | ((pEncodeData[i + 2] >> 6) & 0x03)));strBase64.push_back(BASE64_ENCODE_TABLE.at(pEncodeData[i + 2] & 0x3f));}if (i < nLength){strBase64.push_back(BASE64_ENCODE_TABLE.at((pEncodeData[i] >> 2) & 0x3f));if (i + 1 < nLength){strBase64.push_back(BASE64_ENCODE_TABLE.at(((pEncodeData[i] & 0x03) << 4) | ((pEncodeData[i + 1] >> 4) & 0x0f)));strBase64.push_back(BASE64_ENCODE_TABLE.at(((pEncodeData[i + 1] & 0x0f) << 2)));}else{strBase64.push_back(BASE64_ENCODE_TABLE.at(((pEncodeData[i] & 0x03) << 4)));strBase64.push_back(BASE64_END_CHARACTER);}strBase64.push_back(BASE64_END_CHARACTER);}return strBase64; }int Base64Utils::Decode(const string& strBase64, unsigned char* pOutBuffer, int nLength) {nLength = abs(nLength);int nBase64 = strBase64.length();/** 不符合 base64 字符串长度要求的字符串, 不是 base64 编码格式的字符串, 返回 0 */if ((nBase64 == 0) || ((nBase64 % 4) != 0)) {return 0;}int nNeedSize = nBase64 * 3 / 4;if (strBase64.at(nBase64 - 1) == BASE64_END_CHARACTER)nNeedSize--;if (strBase64.at(nBase64 - 2) == BASE64_END_CHARACTER)nNeedSize--;if (0 == nLength){return nNeedSize;}nNeedSize = min(nNeedSize, nLength);const int nSizeOfDecode = sizeof(BASE64_DECODE_TABLE);int index = 0;int k = 0;unsigned char byteValue;unsigned char base64Char;unsigned char base64Arr[4] = {0};for (int i = 0; i < nBase64; i++){base64Char = strBase64.at(i);if (base64Char == BASE64_END_CHARACTER) // 遇到结速符 {break;}/**如果 base64字符为编码表中只有一个字符, 其解码后值一定为 0否则, 到解码表中查找对应的值, 如果找到, 并且值不为 0, 才是符合的 base64 编码的字符.如果不是 base64 编码表中的字符, 则解码失败, 设置返回值为 0*/if (base64Char == BASE64_ENCODE_TABLE.at(0)){byteValue = 0;}else{if (base64Char < nSizeOfDecode){byteValue = BASE64_DECODE_TABLE[base64Char];}if (byteValue == 0){nNeedSize = 0;break;}}base64Arr[k++] = byteValue;if (k == 4){if (index >= nNeedSize)break;pOutBuffer[index++] = ((base64Arr[0] & 0x3f) << 2) | ((base64Arr[1] & 0x30) >> 4);if (index >= nNeedSize)break;pOutBuffer[index++] = ((base64Arr[1] & 0x0f) << 4) | ((base64Arr[2] & 0x3c) >> 2);if (index >= nNeedSize)break;pOutBuffer[index++] = ((base64Arr[2] & 0x03) << 6) | ((base64Arr[3] & 0x3f));k = 0;}}if ((k != 0) && (index < nNeedSize)){for (; k < 4; k++){base64Arr[k] = 0;}if (index < nNeedSize)pOutBuffer[index++] = ((base64Arr[0] & 0x3f) << 2) | ((base64Arr[1] & 0x30) >> 4);if (index < nNeedSize)pOutBuffer[index++] = ((base64Arr[1] & 0x0f) << 4) | ((base64Arr[2] & 0x3c) >> 2);if (index < nNeedSize)pOutBuffer[index++] = ((base64Arr[2] & 0x03) << 6) | ((base64Arr[3] & 0x3f));}return nNeedSize; }string Base64Utils::DecodeToString(const string& strBase64) {string strResult;int nSize = Decode(strBase64, NULL, 0);if (nSize == 0){return strResult;}unsigned char* pOutBuffer = new unsigned char[nSize + 1];if (!pOutBuffer){return strResult;}pOutBuffer[nSize] = 0;nSize = Decode(strBase64, pOutBuffer, nSize);if (nSize != 0){strResult = reinterpret_cast<char*>(pOutBuffer);}delete[] pOutBuffer;pOutBuffer = NULL;return strResult; }
测试代码
#include "stdafx.h" #include <stdio.h> #include <stdlib.h> #include <iostream> #include "Base64Utils.h"#define PRINT_BYTE(str, len) {printf("[%03d]", len); for(int t = 0; t < len; t++) printf("%c", str[t]); printf("\n");}int _tmain(int argc, _TCHAR* argv[]) {unsigned char pBuffer[] = "~!@#$%^&\0*(\t)_+{}:\"?></.,;'[]\\";int nCount = sizeof(pBuffer);printf("count=%d\n", nCount);for (int i = 1; i <= nCount; i++){string str(&pBuffer[0], &pBuffer[i]);printf("---------- input %d ------------\n", i);printf("%s\n", str.c_str());string strBase64My = Base64Utils::Encode(pBuffer, i);printf("%s\n", strBase64My.c_str());int nOutSize = Base64Utils::Decode(strBase64My, NULL, 0);printf("need buffer : %d\n", nOutSize);//printf("decode:%s\n", Base64Utils::DecodeToString(strBase64My).c_str());//if (strBase64My.length() > 2)//{// strBase64My.replace(strBase64My.begin() + 2, strBase64My.begin() + 3, 1, ',');// printf("%s\n", strBase64My.c_str());//}int j = nOutSize;for (; j > 0; j--){unsigned char* pOutBuffer = new unsigned char[j + 1];memset(pOutBuffer, 0, j + 1);//pOutBuffer[j] = 0;j = Base64Utils::Decode(strBase64My, pOutBuffer, j);// printf("[%03d]%s\n", j, pOutBuffer); PRINT_BYTE(pOutBuffer, j);delete[] pOutBuffer;pOutBuffer = NULL;}}system("pause");return 0; }
转载于:https://www.cnblogs.com/diysoul/p/5816240.html
Base64 编解码相关推荐
- 通过OpenSSL的接口实现Base64编解码
对openssl genrsa产生的rsa私钥pem文件,使用普通的base64解码会有问题,如使用https://blog.csdn.net/fengbingchun/article/details ...
- Java实现BASE64编解码
Java实现BASE64编解码 作者:chszs,转载需注明.博客主页:http://blog.csdn.net/chszs BASE64和其它类似的编码算法通经常使用于转换二进制数据为文本数据,其目 ...
- python 图片base64 编解码,转换成Opencv,PIL.Image图片格式
Python PIL.Image和OpenCV图像格式相互转换 二进制打开图片文件,base64编解码转成Opencv格式: # coding: utf-8 import base64 import ...
- Delphi 自带的 Base64 编解码函数
今天帮别人解决一个关于 Base64 编解码的问题,竟然发现 Delphi 自带了 Base64 编解码的单元,叫 EncdDecd,这名字很拗口而且不直观,估计这是一直很少人关注和知道的原因. 这个 ...
- Java 8实现BASE64编解码
Java 8实现BASE64编解码 作者:chszs,转载需注明.博客主页:http://blog.csdn.net/chszs Java一直缺少BASE64编码 API,以至于通常在项目开发中会选用 ...
- Notepad++插件Base64编解码
我们平常进行Base64编码需要自己写代码转换, 或者使用其他人编写的小工具程序, 也可以使用在线base64编码工具, 现在我们还可以使用Notepad++自带的插件, 进行Base64编码和解码, ...
- Python学习教程:Python3内置模块之base64编解码方法小结
Python学习教程:Python3内置模块之base64编解码方法小结 概述 Base64 是网络上最常见的用于传输 8Bit 字节码的编码方式之一,Base64 就是一种基于 64 个可打印字符来 ...
- ubuntu下c++中base64编解码测试和图片编解码测试
全栈工程师开发手册 (作者:栾鹏) 架构系列文章 字符数组的base64编解码 base64.h #include <string>std::string base64_encode(un ...
- MSDK手Q邀请透传参数问题:url编解码与base64编解码
最近做MSDK手Q的邀请功能,遇到一个坑,手Q结构化消息分享功能接口如下: /*** @param scene 标识发送手Q会话或者Qzone* eQQScene.QQScene_QZone: 分享到 ...
- delphi Base64 编解码
Delphi 自带了 Base64 编解码的单元,叫 EncdDecd,这名字很拗口而且不直观,估计这是一直很少人关注和知道的原因. 这个单元提供两套四个公开函数: 对流的编解码: procedure ...
最新文章
- 解决'ping' 不是内部或外部命令,也不是可运行的程序
- python输入字符串从大到小排列_791. 自定义字符串排序(Python)
- 原生 ajax查询,原生ajax啦啦啦
- Transformer解析
- R语言数据转换(split-apply-combin…
- php5.6 连接 oracle,XAMPP中PHP5.6.3连接Oracle
- 【记录】IDEA未正确关闭导致打开报错,进不了主界面,含解决办法
- C++之指针探究(九):结构体指针
- CVPR 2019接收论文公布:共1300篇,接收率降4%,你中了没?
- Git(7):git撤销已经push到远端的commit
- Sketch2AE插件(Sketch文件导入AE)最新破解版
- CAD图清晰打印设置
- comsol操作技巧
- java版12306抢票_J12306
- 交换机端口与MAC绑定
- 基于机器学习场景,如何搭建特征数据管理中台?
- 【CS231n】斯坦福大学李飞飞视觉识别课程笔记(四):图像分类笔记(上)
- 深度解析服务器科普知识
- 春节大优惠,蓝牙耳机推荐,低延迟日常通勤必备蓝牙耳机
- GMS2的一些常用函数记录
热门文章
- CAN总线技术 | 物理层04 - 终端电阻与双绞线(特性阻抗120欧)
- python解析html xml最好的模块_python中处理xml的模块哪个好?
- 最新SSM完整模板(Spring+SpringMVC+MybatisPlus)
- 【Ant Design Vue】之layout布局
- ue查找文件中每行第二个单词_UI设计和UE/UX设计有什么区别?它们的晋升路径是什么?...
- python格式化转换_(转)python 格式化输出及%用法
- WebQML笔记-qml获取canvas中元素是否被按下
- Java工作笔记-使用fastjson把对象直接生成为Json
- C++设计模式-适配器模式
- C/C++轻松实现文件下载