Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,Base64编码可用于在HTTP环境下传递较长的标识信息。在其他应用程序中,也常常需要把二进制数据编码为适合放在URL(包括隐藏表单域)中的形式。此时,采用Base64编码具有不可读性,即所编码的数据不会被人用肉眼所直接看到。金融数据也常以base64编码格式提供。

Base64是一种基于64个可打印字符来表示二进制数据的表示方法。由于2的6次方等于64,所以每6个比特为一个单元,对应某个可打印字符。三个字节有24个比特,对应于4个Base64单元,即3个字节需要用4个可打印字符来表示。它可用来作为电子邮件的传输编码。在Base64中的可打印字符包括字母A-Z、a-z、数字0-9,这样共有62个字符,此外两个可打印符号在不同的系统中而不同。一些如uuencode的其他编码方法,和之后binhex的版本使用不同的64字符集来代表6个二进制数字,但是它们不叫Base64。

Base64索引表


C++实现代码




1. 《Base64.h》

  1. // Base64.h
  2. #pragma once
  3. #include <windows.h>
  4.  
  5. class CBase64
  6. {
  7. // Internal bucket class.
  8. class TempBucket
  9. {
  10. public:
  11. BYTE nData[4];
  12. BYTE nSize;
  13. void Clear() { ::ZeroMemory(nData, 4); nSize = 0; };
  14. };
  15.  
  16. PBYTE m_pDBuffer;
  17. PBYTE m_pEBuffer;
  18. DWORD m_nDBufLen;
  19. DWORD m_nEBufLen;
  20. DWORD m_nDDataLen;
  21. DWORD m_nEDataLen;
  22.  
  23. public:
  24. CBase64();
  25. virtual ~CBase64();
  26.  
  27. public:
  28. virtual PBYTE Encode(const PBYTE, DWORD);
  29. virtual PBYTE Decode(const PBYTE, DWORD);
  30. virtual CString Encode(LPCSTR sMessage);
  31. virtual CString Decode(LPCSTR sMessage);
  32.  
  33. virtual LPCSTR DecodedMessage() const;
  34. virtual LPCSTR EncodedMessage() const;
  35.  
  36. virtual void AlloCEncodeDlg(DWORD);
  37. virtual void AllocDecode(DWORD);
  38. virtual void SetEncodeBuffer(const PBYTE pBuffer, DWORD nBufLen);
  39. virtual void SetDecodeBuffer(const PBYTE pBuffer, DWORD nBufLen);
  40.  
  41. protected:
  42. virtual void _EncodeToBuffer(const TempBucket &Decode, PBYTE pBuffer);
  43. virtual ULONG _DecodeToBuffer(const TempBucket &Decode, PBYTE pBuffer);
  44. virtual void _EncodeRaw(TempBucket &, const TempBucket &);
  45. virtual void _DecodeRaw(TempBucket &, const TempBucket &);
  46. virtual BOOL _IsBadMimeChar(BYTE);
  47.  
  48. static char m_DecodeTable[256];
  49. static BOOL m_Init;
  50. void _Init();
  51. };

2. 《CBase64.cpp》

  1. // CBase64.cpp
  2. // CBase64.cpp: implementation of the CBase64 class.
  3.  
  4. //////////////////////////////////////////////////////////////////////
  5. #include "stdAfx.h"
  6. #include "Base64.h"
  7. #include "DataX.h"
  8.  
  9. using namespace DataX;
  10.  
  11. // Digits...
  12. static char Base64Digits[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  13.  
  14. BOOL CBase64::m_Init = FALSE;
  15. char CBase64::m_DecodeTable[256];
  16.  
  17. #ifndef PAGESIZE
  18. #define PAGESIZE 4096
  19. #endif
  20.  
  21. #ifndef ROUNDTOPAGE
  22. #define ROUNDTOPAGE(a) ((((a) / 4096) + 1) * 4096)
  23. #endif
  24.  
  25. //////////////////////////////////////////////////////////////////////
  26. // Construction/Destruction
  27. //////////////////////////////////////////////////////////////////////
  28.  
  29. CBase64::CBase64()
  30. : m_pDBuffer(NULL),
  31. m_pEBuffer(NULL),
  32. m_nDBufLen(0),
  33. m_nEBufLen(0)
  34. {
  35.  
  36. }
  37.  
  38. CBase64::~CBase64()
  39. {
  40. if (m_pDBuffer != NULL)
  41. {
  42. delete [] m_pDBuffer;
  43. }
  44.  
  45. if (m_pEBuffer != NULL)
  46. {
  47. delete [] m_pEBuffer;
  48. }
  49. }
  50.  
  51. LPCSTR CBase64::DecodedMessage() const
  52. {
  53. return (LPCSTR) m_pDBuffer;
  54. }
  55.  
  56. LPCSTR CBase64::EncodedMessage() const
  57. {
  58. return (LPCSTR) m_pEBuffer;
  59. }
  60.  
  61. void CBase64::AlloCEncodeDlg(DWORD nSize)
  62. {
  63. if (m_nEBufLen < nSize)
  64. {
  65. if (m_pEBuffer != NULL)
  66. delete [] m_pEBuffer;
  67.  
  68. m_nEBufLen = ROUNDTOPAGE(nSize);
  69. m_pEBuffer = new BYTE[m_nEBufLen];
  70. }
  71.  
  72. ::ZeroMemory(m_pEBuffer, m_nEBufLen);
  73. m_nEDataLen = 0;
  74. }
  75.  
  76. void CBase64::AllocDecode(DWORD nSize)
  77. {
  78. if (m_nDBufLen < nSize)
  79. {
  80. if (m_pDBuffer != NULL)
  81. {
  82. delete [] m_pDBuffer;
  83. }
  84.  
  85. m_nDBufLen = ROUNDTOPAGE(nSize);
  86. m_pDBuffer = new BYTE[m_nDBufLen];
  87. }
  88.  
  89. ::ZeroMemory(m_pDBuffer, m_nDBufLen);
  90. m_nDDataLen = 0;
  91. }
  92.  
  93. void CBase64::SetEncodeBuffer(const PBYTE pBuffer, DWORD nBufLen)
  94. {
  95. DWORD ii = 0;
  96.  
  97. AlloCEncodeDlg(nBufLen);
  98. while(ii < nBufLen)
  99. {
  100. if (!_IsBadMimeChar(pBuffer[ii]))
  101. {
  102. m_pEBuffer[m_nEDataLen] = pBuffer[ii];
  103. m_nEDataLen ++ ;
  104. }
  105.  
  106. ii ++ ;
  107. }
  108. }
  109.  
  110. void CBase64::SetDecodeBuffer(const PBYTE pBuffer, DWORD nBufLen)
  111. {
  112. AllocDecode(nBufLen);
  113. ::CopyMemory(m_pDBuffer, pBuffer, nBufLen);
  114. m_nDDataLen = nBufLen;
  115. }
  116.  
  117. PBYTE CBase64::Encode(const PBYTE pBuffer, DWORD nBufLen)
  118. {
  119. SetDecodeBuffer(pBuffer, nBufLen);
  120. AlloCEncodeDlg(nBufLen * 2);
  121.  
  122. TempBucket Raw;
  123. DWORD nIndex = 0;
  124.  
  125. while((nIndex + 3) <= nBufLen)
  126. {
  127. Raw.Clear();
  128. ::CopyMemory(&Raw, m_pDBuffer + nIndex, 3);
  129. Raw.nSize = 3;
  130. _EncodeToBuffer(Raw, m_pEBuffer + m_nEDataLen);
  131. nIndex += 3;
  132.  
  133. m_nEDataLen += 4;
  134. }
  135.  
  136. if (nBufLen > nIndex)
  137. {
  138. Raw.Clear();
  139. Raw.nSize = (BYTE) (nBufLen - nIndex);
  140. ::CopyMemory(&Raw, m_pDBuffer + nIndex, nBufLen - nIndex);
  141. _EncodeToBuffer(Raw, m_pEBuffer + m_nEDataLen);
  142. m_nEDataLen += 4;
  143. }
  144.  
  145. return m_pEBuffer;
  146. }
  147.  
  148. CString CBase64::Encode(LPCSTR szMessage)
  149. {
  150. CString strHex = _T("");
  151. if (szMessage != NULL)
  152. {
  153. CBase64::Encode((const PBYTE)szMessage, lstrlenA(szMessage));
  154. if (m_nEDataLen > 0)
  155. {
  156. AscToHex(m_pEBuffer, m_nEDataLen, strHex);
  157. }
  158. }
  159.  
  160. return strHex;
  161. }
  162.  
  163. PBYTE CBase64::Decode(const PBYTE pBuffer, DWORD dwBufLen)
  164. {
  165. if (!CBase64::m_Init)
  166. _Init();
  167.  
  168. SetEncodeBuffer(pBuffer, dwBufLen);
  169.  
  170. AllocDecode(dwBufLen);
  171.  
  172. TempBucket Raw;
  173.  
  174. DWORD nIndex = 0;
  175.  
  176. while((nIndex + 4) <= m_nEDataLen)
  177. {
  178. Raw.Clear();
  179. Raw.nData[0] = CBase64::m_DecodeTable[m_pEBuffer[nIndex]];
  180. Raw.nData[1] = CBase64::m_DecodeTable[m_pEBuffer[nIndex + 1]];
  181. Raw.nData[2] = CBase64::m_DecodeTable[m_pEBuffer[nIndex + 2]];
  182.  
  183. Raw.nData[3] = CBase64::m_DecodeTable[m_pEBuffer[nIndex + 3]];
  184.  
  185. if (Raw.nData[2] == 255)
  186. Raw.nData[2] = 0;
  187. if (Raw.nData[3] == 255)
  188. Raw.nData[3] = 0;
  189.  
  190. Raw.nSize = 4;
  191. _DecodeToBuffer(Raw, m_pDBuffer + m_nDDataLen);
  192. nIndex += 4;
  193. m_nDDataLen += 3;
  194. }
  195.  
  196. // If nIndex < m_nEDataLen, then we got a decode message without padding.
  197. // We may want to throw some kind of warning here, but we are still required
  198. // to handle the decoding as if it was properly padded.
  199. if (nIndex < m_nEDataLen)
  200. {
  201. Raw.Clear();
  202. for(DWORD ii = nIndex; ii < m_nEDataLen; ii ++ )
  203. {
  204. Raw.nData[ii - nIndex] = CBase64::m_DecodeTable[m_pEBuffer[ii]];
  205. Raw.nSize ++ ;
  206. if (Raw.nData[ii - nIndex] == 255)
  207. Raw.nData[ii - nIndex] = 0;
  208. }
  209.  
  210. _DecodeToBuffer(Raw, m_pDBuffer + m_nDDataLen);
  211. m_nDDataLen += (m_nEDataLen - nIndex);
  212. }
  213.  
  214. return m_pDBuffer;
  215. }
  216.  
  217. CString CBase64::Decode(LPCSTR pszMessage)
  218. {
  219. if (!pszMessage)
  220. {
  221. return _T("");
  222. }
  223.  
  224. CBase64::Decode((const PBYTE)pszMessage, lstrlenA(pszMessage));
  225. CString strHex = _T("");
  226. if (m_nDDataLen > 0)
  227. {
  228. AscToHex(m_pDBuffer, m_nDDataLen, strHex);
  229. }
  230.  
  231. return strHex;
  232.  
  233. }
  234.  
  235. DWORD CBase64::_DecodeToBuffer(const TempBucket &Decode, PBYTE pBuffer)
  236. {
  237. TempBucket Data;
  238. DWORD nCount = 0;
  239.  
  240. _DecodeRaw(Data, Decode);
  241.  
  242. for(int ii = 0; ii < 3; ii ++ )
  243. {
  244. pBuffer[ii] = Data.nData[ii];
  245. if (pBuffer[ii] != 255)
  246. nCount ++ ;
  247. }
  248.  
  249. return nCount;
  250. }
  251.  
  252. void CBase64::_EncodeToBuffer(const TempBucket &Decode, PBYTE pBuffer)
  253. {
  254. TempBucket Data;
  255.  
  256. _EncodeRaw(Data, Decode);
  257.  
  258. for(int ii = 0; ii < 4; ii ++ )
  259. pBuffer[ii] = Base64Digits[Data.nData[ii]];
  260.  
  261. switch(Decode.nSize)
  262. {
  263. case 1:
  264. pBuffer[2] = '=';
  265.  
  266. case 2:
  267. pBuffer[3] = '=';
  268. }
  269. }
  270.  
  271. void CBase64::_DecodeRaw(TempBucket &Data, const TempBucket &Decode)
  272. {
  273. BYTE nTemp;
  274.  
  275. Data.nData[0] = Decode.nData[0];
  276. Data.nData[0] <<= 2;
  277.  
  278. nTemp = Decode.nData[1];
  279. nTemp >>= 4;
  280. nTemp &= 0x03;
  281. Data.nData[0] |= nTemp;
  282.  
  283. Data.nData[1] = Decode.nData[1];
  284. Data.nData[1] <<= 4;
  285.  
  286. nTemp = Decode.nData[2];
  287. nTemp >>= 2;
  288. nTemp &= 0x0F;
  289. Data.nData[1] |= nTemp;
  290.  
  291. Data.nData[2] = Decode.nData[2];
  292. Data.nData[2] <<= 6;
  293. nTemp = Decode.nData[3];
  294. nTemp &= 0x3F;
  295. Data.nData[2] |= nTemp;
  296. }
  297.  
  298. void CBase64::_EncodeRaw(TempBucket &Data, const TempBucket &Decode)
  299. {
  300. BYTE nTemp;
  301.  
  302. Data.nData[0] = Decode.nData[0];
  303. Data.nData[0] >>= 2;
  304.  
  305. Data.nData[1] = Decode.nData[0];
  306. Data.nData[1] <<= 4;
  307. nTemp = Decode.nData[1];
  308. nTemp >>= 4;
  309. Data.nData[1] |= nTemp;
  310. Data.nData[1] &= 0x3F;
  311.  
  312. Data.nData[2] = Decode.nData[1];
  313. Data.nData[2] <<= 2;
  314.  
  315. nTemp = Decode.nData[2];
  316. nTemp >>= 6;
  317.  
  318. Data.nData[2] |= nTemp;
  319. Data.nData[2] &= 0x3F;
  320.  
  321. Data.nData[3] = Decode.nData[2];
  322. Data.nData[3] &= 0x3F;
  323. }
  324.  
  325. BOOL CBase64::_IsBadMimeChar(BYTE nData)
  326. {
  327. switch(nData)
  328. {
  329. case '\r': case '\n': case '\t': case ' ' :
  330. case '\b': case '\a': case '\f': case '\v':
  331. return TRUE;
  332.  
  333. default:
  334. return FALSE;
  335. }
  336. }
  337.  
  338. void CBase64::_Init()
  339. {
  340. // Initialize Decoding table.
  341. int ii;
  342.  
  343. for(ii = 0; ii < 256; ii ++ )
  344. CBase64::m_DecodeTable[ii] = -2;
  345.  
  346. for(ii = 0; ii < 64; ii ++ )
  347. {
  348. CBase64::m_DecodeTable[Base64Digits[ii]] = (CHAR)ii;
  349. CBase64::m_DecodeTable[Base64Digits[ii]|0x80] = (CHAR)ii;
  350. }
  351.  
  352. CBase64::m_DecodeTable['='] = -1;
  353.  
  354. CBase64::m_DecodeTable['='|0x80] = -1;
  355.  
  356. CBase64::m_Init = TRUE;
  357. }

文/yanxin8原创,获取更多信息请访问http://yanxin8.com/277.html

算法系列8《Base64》的更多相关文章

  1. 1.Java 加解密技术系列之 BASE64

    Java 加解密技术系列之 BASE64 序号 背景 正文 总结 序 这段时间,工作中 用到了 Java 的加解密技术,本着学习的态度,打算从这篇文章开始,详细的研究一番 Java 在加解密技术上有什 ...

  2. JAVA算法系列 冒泡排序

    java算法系列之排序 手写冒泡 冒泡算是最基础的一个排序算法,简单的可以理解为,每一趟都拿i与i+1进行比较,两个for循环,时间复杂度为 O(n^2),同时本例与选择排序进行了比较,选择排序又叫直 ...

  3. JAVA算法系列 快速排序

    java算法系列之排序 手写快排 首先说一下什么是快排,比冒泡效率要高,快排的基本思路是首先找到一个基准元素,比如数组中最左边的那个位置,作为基准元素key,之后在最左边和最右边设立两个哨兵,i 和 ...

  4. javascript实现数据结构与算法系列:栈 -- 顺序存储表示和链式表示及示例

    栈(Stack)是限定仅在表尾进行插入或删除操作的线性表.表尾为栈顶(top),表头为栈底(bottom),不含元素的空表为空栈. 栈又称为后进先出(last in first out)的线性表. 堆 ...

  5. 三白话经典算法系列 Shell排序实现

    山是包插入的精髓排序排序,这种方法,也被称为窄增量排序.因为DL.Shell至1959提出命名. 该方法的基本思想是:先将整个待排元素序列切割成若干个子序列(由相隔某个"增量"的元 ...

  6. Atitit s2018.6 s6 doc list on com pc.docx Atitit s2018.6 s6 doc list on com pc.docx  Aitit algo fix 算法系列补充.docx Atiitt 兼容性提示的艺术 attilax总结.docx Atitit 应用程序容器化总结 v2 s66.docx Atitit file cms api

    Atitit s2018.6 s6  doc list on com pc.docx Atitit s2018.6 s6  doc list on com pc.docx  Aitit algo fi ...

  7. 【C#实现漫画算法系列】-判断 2 的乘方

    微信上关注了算法爱好者这个公众号,有一个漫画算法系列的文章生动形象,感觉特别好,给大家推荐一下(没收过广告费哦),原文链接:漫画算法系列.也看到了许多同学用不同的语言来实现算法,作为一枚C#资深爱好的 ...

  8. 玩转算法系列--图论精讲 面试升职必备(Java版)

    第1章 和bobo老师一起,玩转图论算法欢迎大家来到我的新课程:<玩转图论算法>.在这个课程中,我们将一起完整学习图论领域的经典算法,培养大家的图论建模能力.通过这个课程的学习,你将能够真 ...

  9. 数据结构与算法系列——排序(4)_Shell希尔排序

    1. 工作原理(定义) 希尔排序,也称递减增量排序算法,是插入排序的一种更高效的改进版本.但希尔排序是非稳定排序算法. 希尔排序的基本思想是:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入 ...

  10. 编程作业1.1——sklearn机器学习算法系列之LinearRegression线性回归

    知识点 scikit-learn 对于线性回归提供了比较多的类库,这些类库都可以用来做线性回归分析. 我们也可以使用scikit-learn的线性回归函数,而不是从头开始实现这些算法. 我们将scik ...

随机推荐

  1. 凸包(Convex Hull)构造算法——Graham扫描法

    凸包(Convex Hull) 在图形学中,凸包是一个非常重要的概念.简明的说,在平面中给出N个点,找出一个由其中某些点作为顶点组成的凸多边形,恰好能围住所有的N个点. 这十分像是在一块木板上钉了N个 ...

  2. Java程序员面试宝典1 ---Java基础部分(该博文为原创,转载请注明出处)

    (该博文为原创,转载请注明出处   http://www.cnblogs.com/luyijoy/  by白手伊凡) 1.    基本概念 1)         Java为解释性语言,运行过程:程序源 ...

  3. body-content取值的意义

    body-content的值有下面4种: <xsd:enumeration value="tagdependent"/> <xsd:enumeration val ...

  4. sublime text编辑器删除已安装的插件

    1.ctr+shift+P,输入package2.查找remove package3.输入你要删除的package4.回车,OK

  5. It English 每日更新

    unary operator 一元运算符 short circuit evaluation 短路经查询

  6. 缓存之Redis

    Redis redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(sorte ...

  7. Android基础总结(9)——网络技术

    这里主要讲的是如何在手机端使用HTTP协议和服务器端进行网络交互,并对服务器返回的数据进行解析,这也是Android最常使用到的网络技术了. 1.WebView的用法 Android提供的WebVie ...

  8. [Nginx 2] form表单提交,图片上传

    导读:昨晚恶补了一些Nginx服务器的东西,从整体上对Nginx有一个初步的了解.上午去找师哥问了问目前项目中的使用情况,然后就开始上传图片了.这里就简单总结整理一下今天的成果,以后接着提升.简单粗暴 ...

  9. hadoop,hbase,pig安装

    注意端口,办公网只能访问8000-9000的端口 pig的一些lib文件版本 /home/map/hadoop/lib下一些98.5的lib没删除

  10. oracle查询使用频率和磁盘消耗需要缓存大小

    SELECT * FROM (SELECT Sql_Text, Sql_Id, Cpu_Time FROM V$sql ORDER BY Cpu_Time DESC) ORDER BY Rownum ...