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。

  1. Base64编码表
  2. 码值 字符 码值 字符 码值 字符 码值 字符
  3. A Q g w
  4. B R h x
  5. C S i y
  6. D T j z
  7. E U k
  8. F V l
  9. G W m
  10. H X n
  11. I Y o
  12. J Z p
  13. K a q
  14. L b r
  15. M c s
  16. N d t
  17. O e u +
  18. P f v /

C++实现

  1. #ifndef __BASE64_UTILS__
  2. #define __BASE64_UTILS__
  3.  
  4. #include <string>
  5.  
  6. using std::string;
  7.  
  8. class Base64Utils
  9. {
  10. public:
  11. Base64Utils(void);
  12. ~Base64Utils(void);
  13.  
  14. /**
  15. 将一个字节数组中的数据转为一个 base64 格式的数组
  16. */
  17. static string Encode(const unsigned char* pEncodeData, int nLength);
  18.  
  19. /**
  20. nLength 为 0 时返回需要 pOutBuffer 需要分配的大小; 否则解码数据, 并存入 pOutBuffer 指向的内存中.
  21. 返回值: 失败时返回0. 否则返回反解码后的字符的个数
  22. */
  23. static int Decode(const string& strBase64, unsigned char* pOutBuffer, int nLength);
  24.  
  25. /** 解析为一个字符串(由调用者确定解出的字符中不包含'\0'才能能调用此函数,否则返回的结果可能不是期望的值) */
  26. static string DecodeToString(const string& strBase64);
  27.  
  28. /** 检查一个字符是否是 base64 编码的字符 */
  29. static bool CheckBase64(unsigned char bas64Char);
  30.  
  31. protected:
  32. template <class T> static T min(T left, T right);
  33. };
  34.  
  35. #endif __BASE64_UTILS__
  1. #include "Base64Utils.h"
  2.  
  3. // Base64 编码所用的字符, 其顺序由 base64 协议规定
  4. static const string BASE64_ENCODE_TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  5.  
  6. // 将 ascii 码表中, 对应的 Base64 字符的改成 Base64 字符表中的索引值, 以便解码时进行转行转换
  7. static const unsigned char BASE64_DECODE_TABLE[] =
  8. {
  9. , , , , , , , , , , , , , , , , , , , , , , , ,
  10. , , , , , , , , , , , , , , , , , , ,
  11. , // '+'
  12. , , ,
  13. , // '/'
  14. , , , , , , , , , , // '0'-'9'
  15. , , , , , , ,
  16. , , , , , , , , , , , , , , , , , , , , , , , , , , // 'A'-'Z'
  17. , , , , , ,
  18. , , , , , , , , , , , , , , , , , , , , , , , , , , // 'a'-'z'
  19. };
  20.  
  21. static const unsigned char BASE64_END_CHARACTER = '=';
  22.  
  23. Base64Utils::Base64Utils(void)
  24. {
  25. }
  26.  
  27. Base64Utils::~Base64Utils(void)
  28. {
  29. }
  30.  
  31. template <class T> T Base64Utils::min(T left, T right)
  32. {
  33. return (left < right) ? left : right;
  34. }
  35.  
  36. bool Base64Utils::CheckBase64(unsigned char bas64Char)
  37. {
  38. return (BASE64_ENCODE_TABLE.find(bas64Char) != -) ? true : false;
  39. }
  40.  
  41. string Base64Utils::Encode(const unsigned char* pEncodeData, int nLength)
  42. {
  43. string strBase64;
  44.  
  45. int i = ;
  46. for (; i + < nLength; i += )
  47. {
  48. strBase64.push_back(BASE64_ENCODE_TABLE.at((pEncodeData[i] >> ) & 0x3f));
  49. strBase64.push_back(BASE64_ENCODE_TABLE.at(((pEncodeData[i] & 0x03) << ) | ((pEncodeData[i + ] >> ) & 0x0f)));
  50. strBase64.push_back(BASE64_ENCODE_TABLE.at(((pEncodeData[i + ] & 0x0f) << ) | ((pEncodeData[i + ] >> ) & 0x03)));
  51. strBase64.push_back(BASE64_ENCODE_TABLE.at(pEncodeData[i + ] & 0x3f));
  52. }
  53.  
  54. if (i < nLength)
  55. {
  56. strBase64.push_back(BASE64_ENCODE_TABLE.at((pEncodeData[i] >> ) & 0x3f));
  57. if (i + < nLength)
  58. {
  59. strBase64.push_back(BASE64_ENCODE_TABLE.at(((pEncodeData[i] & 0x03) << ) | ((pEncodeData[i + ] >> ) & 0x0f)));
  60. strBase64.push_back(BASE64_ENCODE_TABLE.at(((pEncodeData[i + ] & 0x0f) << )));
  61. }
  62. else
  63. {
  64. strBase64.push_back(BASE64_ENCODE_TABLE.at(((pEncodeData[i] & 0x03) << )));
  65. strBase64.push_back(BASE64_END_CHARACTER);
  66. }
  67. strBase64.push_back(BASE64_END_CHARACTER);
  68. }
  69.  
  70. return strBase64;
  71. }
  72.  
  73. int Base64Utils::Decode(const string& strBase64, unsigned char* pOutBuffer, int nLength)
  74. {
  75. nLength = abs(nLength);
  76. int nBase64 = strBase64.length();
  77. /** 不符合 base64 字符串长度要求的字符串, 不是 base64 编码格式的字符串, 返回 0 */
  78. if ((nBase64 == ) || ((nBase64 % ) != ))
  79. {
  80. return ;
  81. }
  82.  
  83. int nNeedSize = nBase64 * / ;
  84. if (strBase64.at(nBase64 - ) == BASE64_END_CHARACTER)
  85. nNeedSize--;
  86. if (strBase64.at(nBase64 - ) == BASE64_END_CHARACTER)
  87. nNeedSize--;
  88.  
  89. if ( == nLength)
  90. {
  91. return nNeedSize;
  92. }
  93.  
  94. nNeedSize = min(nNeedSize, nLength);
  95.  
  96. const int nSizeOfDecode = sizeof(BASE64_DECODE_TABLE);
  97. int index = ;
  98. int k = ;
  99. unsigned char byteValue;
  100. unsigned char base64Char;
  101. unsigned char base64Arr[] = {};
  102. for (int i = ; i < nBase64; i++)
  103. {
  104. base64Char = strBase64.at(i);
  105. if (base64Char == BASE64_END_CHARACTER) // 遇到结速符
  106. {
  107. break;
  108. }
  109.  
  110. /**
  111. 如果 base64字符为编码表中只有一个字符, 其解码后值一定为 0
  112. 否则, 到解码表中查找对应的值, 如果找到, 并且值不为 0, 才是符合的 base64 编码的字符.
  113. 如果不是 base64 编码表中的字符, 则解码失败, 设置返回值为 0
  114. */
  115. if (base64Char == BASE64_ENCODE_TABLE.at())
  116. {
  117. byteValue = ;
  118. }
  119. else
  120. {
  121. if (base64Char < nSizeOfDecode)
  122. {
  123. byteValue = BASE64_DECODE_TABLE[base64Char];
  124. }
  125. if (byteValue == )
  126. {
  127. nNeedSize = ;
  128. break;
  129. }
  130. }
  131.  
  132. base64Arr[k++] = byteValue;
  133.  
  134. if (k == )
  135. {
  136. if (index >= nNeedSize)
  137. break;
  138. pOutBuffer[index++] = ((base64Arr[] & 0x3f) << ) | ((base64Arr[] & 0x30) >> );
  139. if (index >= nNeedSize)
  140. break;
  141. pOutBuffer[index++] = ((base64Arr[] & 0x0f) << ) | ((base64Arr[] & 0x3c) >> );
  142. if (index >= nNeedSize)
  143. break;
  144. pOutBuffer[index++] = ((base64Arr[] & 0x03) << ) | ((base64Arr[] & 0x3f));
  145. k = ;
  146. }
  147. }
  148.  
  149. if ((k != ) && (index < nNeedSize))
  150. {
  151. for (; k < ; k++)
  152. {
  153. base64Arr[k] = ;
  154. }
  155. if (index < nNeedSize)
  156. pOutBuffer[index++] = ((base64Arr[] & 0x3f) << ) | ((base64Arr[] & 0x30) >> );
  157. if (index < nNeedSize)
  158. pOutBuffer[index++] = ((base64Arr[] & 0x0f) << ) | ((base64Arr[] & 0x3c) >> );
  159. if (index < nNeedSize)
  160. pOutBuffer[index++] = ((base64Arr[] & 0x03) << ) | ((base64Arr[] & 0x3f));
  161. }
  162.  
  163. return nNeedSize;
  164. }
  165.  
  166. string Base64Utils::DecodeToString(const string& strBase64)
  167. {
  168. string strResult;
  169. int nSize = Decode(strBase64, NULL, );
  170. if (nSize == )
  171. {
  172. return strResult;
  173. }
  174. unsigned char* pOutBuffer = new unsigned char[nSize + ];
  175. if (!pOutBuffer)
  176. {
  177. return strResult;
  178. }
  179. pOutBuffer[nSize] = ;
  180. nSize = Decode(strBase64, pOutBuffer, nSize);
  181. if (nSize != )
  182. {
  183. strResult = reinterpret_cast<char*>(pOutBuffer);
  184. }
  185. delete[] pOutBuffer;
  186. pOutBuffer = NULL;
  187. return strResult;
  188. }

测试代码

  1. #include "stdafx.h"
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <iostream>
  5. #include "Base64Utils.h"
  6.  
  7. #define PRINT_BYTE(str, len) {printf("[%03d]", len); for(int t = 0; t < len; t++) printf("%c", str[t]); printf("\n");}
  8.  
  9. int _tmain(int argc, _TCHAR* argv[])
  10. {
  11. unsigned char pBuffer[] = "~!@#$%^&\0*(\t)_+{}:\"?></.,;'[]\\";
  12.  
  13. int nCount = sizeof(pBuffer);
  14. printf("count=%d\n", nCount);
  15. for (int i = ; i <= nCount; i++)
  16. {
  17. string str(&pBuffer[], &pBuffer[i]);
  18. printf("---------- input %d ------------\n", i);
  19. printf("%s\n", str.c_str());
  20. string strBase64My = Base64Utils::Encode(pBuffer, i);
  21. printf("%s\n", strBase64My.c_str());
  22.  
  23. int nOutSize = Base64Utils::Decode(strBase64My, NULL, );
  24. printf("need buffer : %d\n", nOutSize);
  25.  
  26. //printf("decode:%s\n", Base64Utils::DecodeToString(strBase64My).c_str());
  27.  
  28. //if (strBase64My.length() > 2)
  29. //{
  30. // strBase64My.replace(strBase64My.begin() + 2, strBase64My.begin() + 3, 1, ',');
  31. // printf("%s\n", strBase64My.c_str());
  32. //}
  33.  
  34. int j = nOutSize;
  35. for (; j > ; j--)
  36. {
  37. unsigned char* pOutBuffer = new unsigned char[j + ];
  38. memset(pOutBuffer, , j + );
  39. //pOutBuffer[j] = 0;
  40. j = Base64Utils::Decode(strBase64My, pOutBuffer, j);
  41. // printf("[%03d]%s\n", j, pOutBuffer);
  42. PRINT_BYTE(pOutBuffer, j);
  43. delete[] pOutBuffer;
  44. pOutBuffer = NULL;
  45. }
  46. }
  47. system("pause");
  48. return ;
  49. }

Base64 编解码的更多相关文章

  1. Delphi Base64 编解码函数

    Delphi 自带 Base64 编解码的单元, EncdDecd这个单元提供两套四个公开函数: 对流的编解码:procedure EncodeStream(Input, Output: TStrea ...

  2. ios Base64编解码工具类及使用

    为了避免明码传递http内容,可以用base64编码后传输,收到方再解码,也方便了2进制数据的字符串式传输. 对于ios来说,google给提供了一个很好的工具类,方便进行base64编解码,当然也可 ...

  3. Java实现BASE64编解码

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

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

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

  5. openssl命令行Base64编解码

    openssl对base64编解码的规范支持较差,用它编解码的结果别的语言如php处理很不方便,注意的几点整理如下 1,如果php加密结果做base64编码长度小于64,则需要添加一个换行符opens ...

  6. python rsa 加密解密 (编解码,base64编解码)

    最近有需求,需要研究一下RSA加密解密安全:在网上百度了一下例子文章,很少有文章介绍怎么保存.传输.打印加密后的文本信息,都是千篇一律的.直接在一个脚本,加密后的文本信息赋于变量,然后立马调用解密.仔 ...

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

    二进制打开图片文件,base64编解码,转成Opencv格式: # coding: utf-8 import base64 import numpy as np import cv2 img_file ...

  8. EasyDarwin开源流媒体云平台中boost Base64编解码后与源长度不匹配的bug

    本文转自EasyDarwin团队Alex的博客:http://blog.csdn.net/cai6811376 EasyDarwin云平台中部分协议使用了Base64编码昨晚报文通信的载体.比如在对摄 ...

  9. C++,Base64编解码字符串或文件

    参考链接:在C语言中使用libb64进行Base64编解码 GitHub地址:https://github.com/BuYishi/cpp_base64_demo base64_demo.cpp #i ...

  10. 【VBA研究】如何用Base64 编解码方法实现简单的加解密

    Base64编码的思想是是采用64个基本的ASCII码字符对数据进行重新编码,将数据变成字符串实现文本传输.由于编码简单,所以很容易实现,代码也是现成的.利用这个编码规则可以实现简单的加解密.编解码方 ...

随机推荐

  1. markdown语法介绍

    1. 标题类 每级标题用"# title"表示,共支持6级标题: 2. 段落类 1.建议用换行符控制: 2.用"<p></p>"控制: ...

  2. Tensorflow - Implement for generating some 3-dimensional phony data and fitting them with a plane.

    Coding according to TensorFlow 官方文档中文版 import tensorflow as tf import numpy as np ''' Intro. for thi ...

  3. day-18 滑动平均模型测试样例

    为了使训练模型在测试数据上有更好的效果,可以引入一种新的方法:滑动平均模型.通过维护一个影子变量,来代替最终训练参数,进行训练模型的验证. 在tensorflow中提供了ExponentialMovi ...

  4. Python3 小工具-ICMP扫描

    from scapy.all import * import optparse import threading import os def scan(ipt): pkt=IP(dst=ipt)/IC ...

  5. HTML5 canvas制作童年的回忆大风车

    今天看到一篇CSS3写的大风车http://www.cnblogs.com/yaojaa/archive/2013/01/30/2882521.html,感觉CSS3太神奇了,这在以前用CSS是想都不 ...

  6. JavaScript闭包总结

    闭包是你家庭中的第三者你在享受着第三者给你带来的便利时,而你的家庭也随时触发前所未有的危机(直男癌患者的观点);闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包的常见的方式,就是在一个函数内部 ...

  7. 下载 编译 Android源代码 和 Android kernel源代码

    下载Android源码简要流程 : a. 获取repo文件: curl http://commondatastorage.googleapis.com/git-repo-downloads/repo ...

  8. python爬虫从入门到放弃(四)之 Requests库的基本使用(转)

    什么是Requests Requests是用python语言基于urllib编写的,采用的是Apache2 Licensed开源协议的HTTP库如果你看过上篇文章关于urllib库的使用,你会发现,其 ...

  9. Android 布局方式学习

    一.LinearLayout线性布局: 线性布局是程序中最常见的一种布局方式,线性布局可以分为水平线性布局和垂直线性布局两种, 通过android:orientation属性可以设置线性布局的方向 1 ...

  10. 【Python】python之set

    阅读目录 一.set集合介绍 二.集合的方法 1.s.add()添加元素 3.s.copy()浅拷贝 4.s.difference(b) 5.s.difference_update(b) 6.s.di ...