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 编解码的更多相关文章

  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. lintcode142 O(1)时间检测2的幂次

    O(1)时间检测2的幂次 用 O(1) 时间检测整数 n 是否是 2 的幂次. 您在真实的面试中是否遇到过这个题? Yes 样例 n=4,返回 true; n=5,返回 false. 二进制的n中只有 ...

  2. 更新字典 (Updating a Dictionary,UVa12504)

    题目描述: 解题思路: 1.根据:和,获得字符串 2.使用两个map进行比较: #include <iostream> #include <algorithm> #includ ...

  3. Android开发-API指南-<permission>

    <permission> 英文原文:http://developer.android.com/guide/topics/manifest/permission-element.html 采 ...

  4. 使用open live writee写的博客

    1. 安装包 下载链接:open live writer 2. 安装及使用教程 学习教程(转载他人) 3. 插入个图片 4. 写段代码 写不了,插件用不了 5. 插件使用: 参考文章:(http:// ...

  5. StreamReader和StreamWriter中文乱码问题

    StreamReader和StreamWriter中文乱码问题 1.写入: string  FilePath = @"E:\Measure.csv"; StreamWriter w ...

  6. halcon安装提示could not write updated path to HKLM

    halcon安装提示could not write updated path to HKLM 我们在安装Halcon软件时,会弹出如上图错误信息,这个错误信息提示软件无法写入本地注册表,造成这个原因有 ...

  7. Python基础简介

    一.目前各种语言的应用:java, 可以把特别小的项目做大,并且开源库比较多,C: 用在最底层,例如编写操作系统,运行速率快,开发效率低,C++:常坐游戏引擎Python:AI(人工智能) 简单.明确 ...

  8. 怎么用js精确判断li已经在ul存在过了?

    <ul class="memory_messagelist" id="memory_messagelist"> <li><span ...

  9. 基础数据类型-tuple

    Python中,元组tuple与list类似,不同之处在于tuple的元素不能修改,tuple使用(),list使用[], (1)元组的创建使用(),需要注意的是创建包含一个元素的元组: tuple_ ...

  10. 欢迎来怼-Alpha周(2017年10月19)贡献分配规则和分配结果

    .从alpha周(2017年10月19日开始的2周)开始,提高贡献分比重. 贡献分 : 团队分 = 1 : 5 教师会在核算每位同学总分时按比例乘以系数. 每位同学带入团队贡献分10分,如果团队一共7 ...