Base64编码说明
  Base64编码要求把3个8位字节(3*8=24)转化为4个6位的字节(4*6=24),之后在6位的前面补两个0,形成8位一个字节的形式。 如果剩下的字符不足3个字节,则用0填充,输出字符使用'=',因此编码后输出的文本末尾可能会出现1或2个'='。

  为了保证所输出的编码位可读字符,Base64制定了一个编码表,以便进行统一转换。编码表的大小为2^6=64,这也是Base64名称的由来。

转码过程举例:
  3*8=4*6
  内存1个字符占8位
  转前: s 1 3
  先转成ascii:对应 115 49 51
  2进制: 01110011 00110001 00110011
  6个一组(4组) 011100110011000100110011
  然后才有后面的 011100 110011 000100 110011
  然后计算机是8位8位的存数 6不够,自动就补两个高位0了
  所有有了 高位补0
  科学计算器输入 00011100 00110011 00000100 00110011
  得到 28 51 4 51
  查对下照表 c z E z

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++实现:

base64.h

 #ifndef _BASE64_HH
#define _BASE64_HH #ifdef __cplusplus
extern "C" {
#endif //__cplusplus unsigned char* base64Decode(char* pszInput, unsigned int& iReturnSize, bool trimTrailingZeros = true); char* base64Encode(char const* origSigned, unsigned iOrigLength); #ifdef __cplusplus
}
#endif //__cplusplus #endif //_BASE64_HH

base64.cpp

 #include "base64.h"
#include <string.h> static char base64DecodeTable[];
//初始化编码对照表
static const char base64Char[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; char* strDupSize(char const* str)
{
if (str == NULL) return NULL;
size_t len = strlen(str) + ;
char* copy = new char[len]; return copy;
} //初始化解码对照表
static void initBase64DecodeTable()
{
for (int i = ; i < ; ++i)
base64DecodeTable[i] = (char)0x80; // default value: invalid for (int i = 'A'; i <= 'Z'; ++i)
base64DecodeTable[i] = + (i - 'A');
for (int i = 'a'; i <= 'z'; ++i)
base64DecodeTable[i] = + (i - 'a');
for (int i = ''; i <= ''; ++i)
base64DecodeTable[i] = + (i - '');
base64DecodeTable[(unsigned char)'+'] = ;
base64DecodeTable[(unsigned char)'/'] = ;
base64DecodeTable[(unsigned char)'='] = ; //0x40
} // 解码
unsigned char* base64Decode(char* pszInput, unsigned int& iReturnSize, bool trimTrailingZeros)
{
static bool haveInitedBase64DecodeTable = false;
if (!haveInitedBase64DecodeTable)
{
initBase64DecodeTable();
haveInitedBase64DecodeTable = true;
} unsigned char* pszOutput = new unsigned char[strlen(pszInput)];
int k = ;
/*******************************************************************************************
*技巧:先减去3 ---in case "pszInput" is not a multiple of 4 bytes (although it should be) *
* 个人觉得这里不用做处理,因为编码时候已经做过处理,密文肯定为4的整数倍 *
*******************************************************************************************/
int const jMax = strlen(pszInput) - ; //将密文四个字节为一组,每组解码为三个字节
for (int j = ; j < jMax; j += )
{
char inTmp[], outTmp[];
for (int i = ; i < ; ++i)
{
inTmp[i] = pszInput[i+j];
outTmp[i] = base64DecodeTable[(unsigned char)inTmp[i]];
if ((outTmp[i]&0x40) != ) //如果遇到'=',将其视为结束字符
outTmp[i] = 0x00;
} pszOutput[k++] = (outTmp[]<<) | (outTmp[]>>);
pszOutput[k++] = (outTmp[]<<) | (outTmp[]>>);
pszOutput[k++] = (outTmp[]<<) | outTmp[];
} if (trimTrailingZeros)
{
while (k > && pszOutput[k-] == '\')
--k;
}
iReturnSize = k;
unsigned char* result = new unsigned char[iReturnSize];
memset(result, , iReturnSize);
memmove(result, pszOutput, iReturnSize);
delete[] pszOutput;
return result;
} // 编码
char* base64Encode(char const* origSigned, unsigned iOrigLength)
{
unsigned char const* orig = (unsigned char const*)origSigned;
if (orig == NULL)
return NULL; unsigned const iNumResultBytes = *(iOrigLength/ + (iOrigLength% ? : ));
char* result = new char[iNumResultBytes + ]; //源码三个字节为一组,编码后将三个字节变为四个字节
unsigned i;
for (i = ; i < iOrigLength/; ++i)
{
// 取源码的第一个字节的前六位,前面加两个零生成第一个字节
result[*i+] = base64Char[(orig[*i]>>) & 0x3F];
// 取源码的第一个字节的后两位和第二个字节的前四位,前面补两个零生成第二个字节
result[*i+] = base64Char[((orig[*i]<<) | (orig[*i+]>>)) & 0x3F];
// 取源码的第二个字节的后四位和第三个字节的前两位,前面补两个零生成第三个字节
result[*i+] = base64Char[((orig[*i+]<<) | (orig[*i+]>>)) & 0x3F];
// 取源码的第三个字节的后六位,前面补两个零生成第四个字节
result[*i+] = base64Char[orig[*i+]&0x3F];
}
//不足三个字节的最后补'='字符,补足三个字节
if (iOrigLength%)
{
result[*i+] = base64Char[(orig[*i]>>) & 0x3F];
if (iOrigLength% == )
{
result[*i+] = base64Char[((orig[*i]<<) | (orig[*i+]>>))&0x3F];
result[*i+] = base64Char[(orig[*i+]<<)&0x3C];
}
else
{
result[*i+] = base64Char[((orig[*i])<<)&0x3F];
result[*i+] = '=';
}
result[*i+] = '=';
} result[iNumResultBytes] = '\0';
return result;
}

测试代码main.cpp

 #include "base64.h"
#include <iostream> using namespace std; int main()
{
cout << "请输入要转换的字符串(支持中文):" << endl;
char szStrOrigin[];
scanf("%s", szStrOrigin);
unsigned int iReturnSize;
cout << "编码之前字符串:" << szStrOrigin << endl;
char *pEncodeStr = base64Encode(szStrOrigin, strlen(szStrOrigin));
cout << "编码之后字符串:" << pEncodeStr << endl;
unsigned char *pDecodeStr = base64Decode(pEncodeStr, iReturnSize);
cout << "解码之后字符串:" << pDecodeStr << endl;
system("pause");
}

运行结果:

 

Base64原理与实现的更多相关文章

  1. Base64原理

    一.Base64编码由来 为什么会有Base64编码呢?因为有些网络传送渠道并不支持所有的字节,例如传统的邮件只支持可见字符的传送,像ASCII码的控制字符就 不能通过邮件传送.这样用途就受到了很大的 ...

  2. Base64原理解析

    一. Base64编码由来 为什么会有Base64编码呢?因为有些网络传送渠道并不支持所有的字节,例如传统的邮件只支持可见字符的传送,像ASCII码的控制字符就 不能通过邮件传送.这样用途就受到了很大 ...

  3. Base64原理解析与使用

    一.Base64编码由来 为什么会有Base64编码呢?因为有些网络传送渠道并不支持所有的字节,例如传统的邮件只支持可见字符的传送,像ASCII码的控制字符就 不能通过邮件传送.这样用途就受到了很大的 ...

  4. 一份简明的 Base64 原理解析

    书接上回,在 记一个 Base64 有关的 Bug 一文里,我们说到了 Base64 的编解码器有不同实现,交叉使用它们可能引发的问题等等. 这一回,我们来对 Base64 这一常用编解码技术的原理一 ...

  5. base64原理,使用场景

    Base64编码,是我们程序开发中经常使用到的编码方法.它是一种基于用64个可打印字符来表示二进制数据的表示方法.它通常用作存储.传输一些二进制数据编码方法!也是MIME(多用途互联网邮件扩展,主要用 ...

  6. Base64原理简介

    Base64是一种编码方式,通常用于将二进制数据转换成可见字符的形式,该过程可逆. 过程大致如下: 1. 对64个可见字符,进行一个索引编码.索引是二进制的值,对应找到一个可见字符. Base64 编 ...

  7. base64 原理

    Base64编码之所以称为Base64,是因为其使用64个字符来对任意数据进行编码,同理有Base32.Base16编码.标准Base64编码使用的64个字符为: 这64个字符是各种字符编码(比如AS ...

  8. Base64原理 bits 3->4 8bits/byte-->6bits/byte

    实践: window.btoa('a')a YQ==abcdef YWJjZGVmabc YWJjab YWI= https://en.wikipedia.org/wiki/Base64 The Ba ...

  9. php base64 原理

    #include <stdio.h> #include <stdlib.h> #include <string.h> static const char base6 ...

随机推荐

  1. Android activity之间数据传递和共享的方式之Application

    1.基于消息的通信机制  Intent ---bundle ,extra 数据类型有限,比如遇到不可序列化的数据Bitmap,InputStream,或者LinkedList链表等等数据类型就不太好用 ...

  2. 20172308《Java软件结构与数据结构》第四周学习总结

    教材学习内容总结 第 6 章 列表 一. 列表集合 列表集合:一种概念性表示法,思想是使事物以线性列表的方式进行组织 特点: 列表集合没有内在的容量大小,它可以随着需要而增大 列表集合更具一般化,可以 ...

  3. CentOS 7 yum 安装subversion

    yum list installed | grep subversionyum install subversioncd /var/wwwsvn -hsvn co svn://121.196.226. ...

  4. java使用代理模拟http get请求

    直接上代码: import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.InetSocketAd ...

  5. Failed to connect socket to '/var/run/libvirt/libvirt-sock'的问题解决

    1.增加libvirtd用户组 groupadd libvirtd 2.设置用户到组 sudo usermod -a -G libvirtd $USER 3.设置启动libvirtd服务的用户组 vi ...

  6. MikroTik RouterOS 5.x使用HunterTik 2.3.1进行破解

    一.加载光驱: 二.一路回车: 三.说明: 1.可以不安装Debian内核,但如果在无缝升级到6.6的版本,此项就一定要选择. 2.6版本的破解必须小于等于1G的空间,不然无法破解成功,亲测有效,如果 ...

  7. STM32学习日志--使用DMA功能自动更新PWM的输出

    /******************************************************************************* 编译环境: EWARM V5.30 硬 ...

  8. MySQL子查询慢现象的解决

    当你在用explain工具查看sql语句的执行计划时,若select_type 字段中出现“DEPENDENT SUBQUERY”时,你要注意了,你已经掉入了mysql子查询慢的“坑". 相 ...

  9. 阅读Linux内核源码时建立tags索引

    比如在阅读arm架构的Linux内核代码时想建立arm架构相关的索引,可以使用下面的命令: make ARCH=arm tags

  10. 基于设备树的TQ2440 DMA学习(1)—— 芯片手册

    作者 彭东林pengdonglin137@163.com 平台 TQ2440内核Linux4.9 概述 一直想抽时间学习一下DMA驱动,今天就以S3C2440为例,这款芯片的DMA控制器足够简单,也比 ...