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 编解码相关推荐

  1. 通过OpenSSL的接口实现Base64编解码

    对openssl genrsa产生的rsa私钥pem文件,使用普通的base64解码会有问题,如使用https://blog.csdn.net/fengbingchun/article/details ...

  2. Java实现BASE64编解码

    Java实现BASE64编解码 作者:chszs,转载需注明.博客主页:http://blog.csdn.net/chszs BASE64和其它类似的编码算法通经常使用于转换二进制数据为文本数据,其目 ...

  3. python 图片base64 编解码,转换成Opencv,PIL.Image图片格式

    Python PIL.Image和OpenCV图像格式相互转换 二进制打开图片文件,base64编解码转成Opencv格式: # coding: utf-8 import base64 import ...

  4. Delphi 自带的 Base64 编解码函数

    今天帮别人解决一个关于 Base64 编解码的问题,竟然发现 Delphi 自带了 Base64 编解码的单元,叫 EncdDecd,这名字很拗口而且不直观,估计这是一直很少人关注和知道的原因. 这个 ...

  5. Java 8实现BASE64编解码

    Java 8实现BASE64编解码 作者:chszs,转载需注明.博客主页:http://blog.csdn.net/chszs Java一直缺少BASE64编码 API,以至于通常在项目开发中会选用 ...

  6. Notepad++插件Base64编解码

    我们平常进行Base64编码需要自己写代码转换, 或者使用其他人编写的小工具程序, 也可以使用在线base64编码工具, 现在我们还可以使用Notepad++自带的插件, 进行Base64编码和解码, ...

  7. Python学习教程:Python3内置模块之base64编解码方法小结

    Python学习教程:Python3内置模块之base64编解码方法小结 概述 Base64 是网络上最常见的用于传输 8Bit 字节码的编码方式之一,Base64 就是一种基于 64 个可打印字符来 ...

  8. ubuntu下c++中base64编解码测试和图片编解码测试

    全栈工程师开发手册 (作者:栾鹏) 架构系列文章 字符数组的base64编解码 base64.h #include <string>std::string base64_encode(un ...

  9. MSDK手Q邀请透传参数问题:url编解码与base64编解码

    最近做MSDK手Q的邀请功能,遇到一个坑,手Q结构化消息分享功能接口如下: /*** @param scene 标识发送手Q会话或者Qzone* eQQScene.QQScene_QZone: 分享到 ...

  10. delphi Base64 编解码

    Delphi 自带了 Base64 编解码的单元,叫 EncdDecd,这名字很拗口而且不直观,估计这是一直很少人关注和知道的原因. 这个单元提供两套四个公开函数: 对流的编解码: procedure ...

最新文章

  1. 解决'ping' 不是内部或外部命令,也不是可运行的程序
  2. python输入字符串从大到小排列_791. 自定义字符串排序(Python)
  3. 原生 ajax查询,原生ajax啦啦啦
  4. Transformer解析
  5. R语言数据转换(split-apply-combin…
  6. php5.6 连接 oracle,XAMPP中PHP5.6.3连接Oracle
  7. 【记录】IDEA未正确关闭导致打开报错,进不了主界面,含解决办法
  8. C++之指针探究(九):结构体指针
  9. CVPR 2019接收论文公布:共1300篇,接收率降4%,你中了没?
  10. Git(7):git撤销已经push到远端的commit
  11. Sketch2AE插件(Sketch文件导入AE)最新破解版
  12. CAD图清晰打印设置
  13. comsol操作技巧
  14. java版12306抢票_J12306
  15. 交换机端口与MAC绑定
  16. 基于机器学习场景,如何搭建特征数据管理中台?
  17. 【CS231n】斯坦福大学李飞飞视觉识别课程笔记(四):图像分类笔记(上)
  18. 深度解析服务器科普知识
  19. 春节大优惠,蓝牙耳机推荐,低延迟日常通勤必备蓝牙耳机
  20. GMS2的一些常用函数记录

热门文章

  1. CAN总线技术 | 物理层04 - 终端电阻与双绞线(特性阻抗120欧)
  2. python解析html xml最好的模块_python中处理xml的模块哪个好?
  3. 最新SSM完整模板(Spring+SpringMVC+MybatisPlus)
  4. 【Ant Design Vue】之layout布局
  5. ue查找文件中每行第二个单词_UI设计和UE/UX设计有什么区别?它们的晋升路径是什么?...
  6. python格式化转换_(转)python 格式化输出及%用法
  7. WebQML笔记-qml获取canvas中元素是否被按下
  8. Java工作笔记-使用fastjson把对象直接生成为Json
  9. C++设计模式-适配器模式
  10. C/C++轻松实现文件下载