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编码表
- 码值 字符 码值 字符 码值 字符 码值 字符
- A Q g w
- B R h x
- C S i y
- D T j z
- E U k
- F V l
- G W m
- H X n
- I Y o
- J Z p
- K a q
- L b r
- M c s
- N d t
- O e u +
- P f v /
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'-'9'
- , , , , , , ,
- , , , , , , , , , , , , , , , , , , , , , , , , , , // 'A'-'Z'
- , , , , , ,
- , , , , , , , , , , , , , , , , , , , , , , , , , , // '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) != -) ? true : false;
- }
- string Base64Utils::Encode(const unsigned char* pEncodeData, int nLength)
- {
- string strBase64;
- int i = ;
- for (; i + < nLength; i += )
- {
- strBase64.push_back(BASE64_ENCODE_TABLE.at((pEncodeData[i] >> ) & 0x3f));
- strBase64.push_back(BASE64_ENCODE_TABLE.at(((pEncodeData[i] & 0x03) << ) | ((pEncodeData[i + ] >> ) & 0x0f)));
- strBase64.push_back(BASE64_ENCODE_TABLE.at(((pEncodeData[i + ] & 0x0f) << ) | ((pEncodeData[i + ] >> ) & 0x03)));
- strBase64.push_back(BASE64_ENCODE_TABLE.at(pEncodeData[i + ] & 0x3f));
- }
- if (i < nLength)
- {
- strBase64.push_back(BASE64_ENCODE_TABLE.at((pEncodeData[i] >> ) & 0x3f));
- if (i + < nLength)
- {
- strBase64.push_back(BASE64_ENCODE_TABLE.at(((pEncodeData[i] & 0x03) << ) | ((pEncodeData[i + ] >> ) & 0x0f)));
- strBase64.push_back(BASE64_ENCODE_TABLE.at(((pEncodeData[i + ] & 0x0f) << )));
- }
- else
- {
- strBase64.push_back(BASE64_ENCODE_TABLE.at(((pEncodeData[i] & 0x03) << )));
- 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 == ) || ((nBase64 % ) != ))
- {
- return ;
- }
- int nNeedSize = nBase64 * / ;
- if (strBase64.at(nBase64 - ) == BASE64_END_CHARACTER)
- nNeedSize--;
- if (strBase64.at(nBase64 - ) == BASE64_END_CHARACTER)
- nNeedSize--;
- if ( == nLength)
- {
- return nNeedSize;
- }
- nNeedSize = min(nNeedSize, nLength);
- const int nSizeOfDecode = sizeof(BASE64_DECODE_TABLE);
- int index = ;
- int k = ;
- unsigned char byteValue;
- unsigned char base64Char;
- unsigned char base64Arr[] = {};
- for (int i = ; 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())
- {
- byteValue = ;
- }
- else
- {
- if (base64Char < nSizeOfDecode)
- {
- byteValue = BASE64_DECODE_TABLE[base64Char];
- }
- if (byteValue == )
- {
- nNeedSize = ;
- break;
- }
- }
- base64Arr[k++] = byteValue;
- if (k == )
- {
- if (index >= nNeedSize)
- break;
- pOutBuffer[index++] = ((base64Arr[] & 0x3f) << ) | ((base64Arr[] & 0x30) >> );
- if (index >= nNeedSize)
- break;
- pOutBuffer[index++] = ((base64Arr[] & 0x0f) << ) | ((base64Arr[] & 0x3c) >> );
- if (index >= nNeedSize)
- break;
- pOutBuffer[index++] = ((base64Arr[] & 0x03) << ) | ((base64Arr[] & 0x3f));
- k = ;
- }
- }
- if ((k != ) && (index < nNeedSize))
- {
- for (; k < ; k++)
- {
- base64Arr[k] = ;
- }
- if (index < nNeedSize)
- pOutBuffer[index++] = ((base64Arr[] & 0x3f) << ) | ((base64Arr[] & 0x30) >> );
- if (index < nNeedSize)
- pOutBuffer[index++] = ((base64Arr[] & 0x0f) << ) | ((base64Arr[] & 0x3c) >> );
- if (index < nNeedSize)
- pOutBuffer[index++] = ((base64Arr[] & 0x03) << ) | ((base64Arr[] & 0x3f));
- }
- return nNeedSize;
- }
- string Base64Utils::DecodeToString(const string& strBase64)
- {
- string strResult;
- int nSize = Decode(strBase64, NULL, );
- if (nSize == )
- {
- return strResult;
- }
- unsigned char* pOutBuffer = new unsigned char[nSize + ];
- if (!pOutBuffer)
- {
- return strResult;
- }
- pOutBuffer[nSize] = ;
- nSize = Decode(strBase64, pOutBuffer, nSize);
- if (nSize != )
- {
- 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 = ; i <= nCount; i++)
- {
- string str(&pBuffer[], &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, );
- 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 > ; j--)
- {
- unsigned char* pOutBuffer = new unsigned char[j + ];
- memset(pOutBuffer, , j + );
- //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 ;
- }
Base64 编解码的更多相关文章
- Delphi Base64 编解码函数
Delphi 自带 Base64 编解码的单元, EncdDecd这个单元提供两套四个公开函数: 对流的编解码:procedure EncodeStream(Input, Output: TStrea ...
- ios Base64编解码工具类及使用
为了避免明码传递http内容,可以用base64编码后传输,收到方再解码,也方便了2进制数据的字符串式传输. 对于ios来说,google给提供了一个很好的工具类,方便进行base64编解码,当然也可 ...
- Java实现BASE64编解码
Java实现BASE64编解码 作者:chszs,转载需注明.博客主页:http://blog.csdn.net/chszs BASE64和其它类似的编码算法通经常使用于转换二进制数据为文本数据,其目 ...
- Delphi 自带的 Base64 编解码函数
今天帮别人解决一个关于 Base64 编解码的问题,竟然发现 Delphi 自带了 Base64 编解码的单元,叫 EncdDecd,这名字很拗口而且不直观,估计这是一直很少人关注和知道的原因. 这个 ...
- openssl命令行Base64编解码
openssl对base64编解码的规范支持较差,用它编解码的结果别的语言如php处理很不方便,注意的几点整理如下 1,如果php加密结果做base64编码长度小于64,则需要添加一个换行符opens ...
- python rsa 加密解密 (编解码,base64编解码)
最近有需求,需要研究一下RSA加密解密安全:在网上百度了一下例子文章,很少有文章介绍怎么保存.传输.打印加密后的文本信息,都是千篇一律的.直接在一个脚本,加密后的文本信息赋于变量,然后立马调用解密.仔 ...
- python base64 编解码,转换成Opencv,PIL.Image图片格式
二进制打开图片文件,base64编解码,转成Opencv格式: # coding: utf-8 import base64 import numpy as np import cv2 img_file ...
- EasyDarwin开源流媒体云平台中boost Base64编解码后与源长度不匹配的bug
本文转自EasyDarwin团队Alex的博客:http://blog.csdn.net/cai6811376 EasyDarwin云平台中部分协议使用了Base64编码昨晚报文通信的载体.比如在对摄 ...
- C++,Base64编解码字符串或文件
参考链接:在C语言中使用libb64进行Base64编解码 GitHub地址:https://github.com/BuYishi/cpp_base64_demo base64_demo.cpp #i ...
- 【VBA研究】如何用Base64 编解码方法实现简单的加解密
Base64编码的思想是是采用64个基本的ASCII码字符对数据进行重新编码,将数据变成字符串实现文本传输.由于编码简单,所以很容易实现,代码也是现成的.利用这个编码规则可以实现简单的加解密.编解码方 ...
随机推荐
- markdown语法介绍
1. 标题类 每级标题用"# title"表示,共支持6级标题: 2. 段落类 1.建议用换行符控制: 2.用"<p></p>"控制: ...
- 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 ...
- day-18 滑动平均模型测试样例
为了使训练模型在测试数据上有更好的效果,可以引入一种新的方法:滑动平均模型.通过维护一个影子变量,来代替最终训练参数,进行训练模型的验证. 在tensorflow中提供了ExponentialMovi ...
- Python3 小工具-ICMP扫描
from scapy.all import * import optparse import threading import os def scan(ipt): pkt=IP(dst=ipt)/IC ...
- HTML5 canvas制作童年的回忆大风车
今天看到一篇CSS3写的大风车http://www.cnblogs.com/yaojaa/archive/2013/01/30/2882521.html,感觉CSS3太神奇了,这在以前用CSS是想都不 ...
- JavaScript闭包总结
闭包是你家庭中的第三者你在享受着第三者给你带来的便利时,而你的家庭也随时触发前所未有的危机(直男癌患者的观点);闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包的常见的方式,就是在一个函数内部 ...
- 下载 编译 Android源代码 和 Android kernel源代码
下载Android源码简要流程 : a. 获取repo文件: curl http://commondatastorage.googleapis.com/git-repo-downloads/repo ...
- python爬虫从入门到放弃(四)之 Requests库的基本使用(转)
什么是Requests Requests是用python语言基于urllib编写的,采用的是Apache2 Licensed开源协议的HTTP库如果你看过上篇文章关于urllib库的使用,你会发现,其 ...
- Android 布局方式学习
一.LinearLayout线性布局: 线性布局是程序中最常见的一种布局方式,线性布局可以分为水平线性布局和垂直线性布局两种, 通过android:orientation属性可以设置线性布局的方向 1 ...
- 【Python】python之set
阅读目录 一.set集合介绍 二.集合的方法 1.s.add()添加元素 3.s.copy()浅拷贝 4.s.difference(b) 5.s.difference_update(b) 6.s.di ...