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. tomcat配置问题:访问http://localhost:8080/ 遇到 Access Error: 404

    win7: 8080端口已经被其他应用使用,比如nixxxxxxxxxxxxx When I had an error Access Error: 404 -- Not Found I fixed i ...

  2. spring cloud 学习(11) - 用fastson替换jackson及用gb2312码输出

    前几天遇到一个需求,因为要兼容旧项目的编码格式,需要spring-cloud的rest接口,输出gb2312编码,本以为是一个很容易的事情,比如下面这样: @RequestMapping(method ...

  3. 20款最好的免费 Bootstrap 后台管理和前端模板

    Admin Bootstrap Templates Free Download 1. SB Admin 2 Preview | Details & Download 2. Admin Lite ...

  4. JTAG TAP Controller

    The TAP controller is a synchronous finite state machine that responds to changes at the TMS and TCK ...

  5. C++ classes and uniform initialization

     // classes and uniform initialization #include <iostream> using namespace std; class Circle ...

  6. leetcode第一刷_Unique Binary Search Trees

    这道题事实上跟二叉搜索树没有什么关系,给定n个节点,让你求有多少棵二叉树也是全然一样的做法.思想是什么呢,给定一个节点数x.求f(x),f(x)跟什么有关系呢,当然是跟他的左右子树都有关系.所以能够利 ...

  7. GPG入门教程

    原文地址:http://www.ruanyifeng.com/blog/2013/07/gpg.html 作者: 阮一峰 日期: 2013年7月12日 前两篇文章,我介绍了RSA算法. 今天,就接着来 ...

  8. Ioc:Autofac Registration Concepts

    Reflection Components When using reflection-based components, Autofac automatically uses the constru ...

  9. YAML 语言教程

    编程免不了要写配置文件,怎么写配置也是一门学问. YAML 是专门用来写配置文件的语言,非常简洁和强大,远比 JSON 格式方便. 本文介绍 YAML 的语法,以 JS-YAML 的实现为例.你可以去 ...

  10. 绝望的主妇第八季/Desperate Housewives迅雷下载

    绝望的主妇 第七季 Desperate Housewives Season 8(2011) 本季看点:曾经在<主妇>中有过重要演出的达娜·德拉尼(Dana Delany), 凯尔·麦克拉克 ...