Base64编码

来源:互联网 发布:51单片机hc05蓝牙例程 编辑:程序博客网 时间:2024/05/08 13:06

参考:

http://www.cnblogs.com/hongru/archive/2012/01/14/2321397.html

关于base64编码的原理及实现

我们的图片大部分都是可以转换成base64编码的data:image。 这个在将canvas保存为img的时候尤其有用。虽然除ie外,大部分现代浏览器都已经支持原生的基于base64的encode和decode,例如btoa和atob。(将canvas画布保存成img并强制改变mimetype进行下载,会在下一篇记录)

但是处于好奇心,还是驱使我去了解下base64编码的原理。以便也在不支持原生base64编码的ie下可以得以实现。

【Base64】
-base64的编码都是按字符串长度,以每3个8bit的字符为一组,
-然后针对每组,首先获取每个字符的ASCII编码,
-然后将ASCII编码转换成8bit的二进制,得到一组3*8=24bit的字节
-然后再将这24bit划分为4个6bit的字节,并在每个6bit的字节前面都填两个高位0,得到4个8bit的字节
-然后将这4个8bit的字节转换成10进制,对照Base64编码表 (下表),得到对应编码后的字符。

(注:1. 要求被编码字符是8bit的,所以须在ASCII编码范围内,\u0000-\u00ff,中文就不行。
   2. 如果被编码字符长度不是3的倍数的时候,则都用0代替,对应的输出字符为=)

Base64 编码表ValueChar ValueChar ValueChar ValueChar0A16Q32g48w1B17R33h49x2C18S34i50y3D19T35j51z4E20U36k5205F21V37l5316G22W38m5427H23X39n5538I24Y40o5649J25Z41p57510K26a42q58611L27b43r59712M28c44s60813N29d45t61914O30e46u62+15P31f47v63/

比如举下面2个例子:
a) 字符长度为能被3整除时:比如“Tom” :

            T           o           mASCII:      84          111         1098bit字节:   01010100    01101111    011011016bit字节:     010101      000110      111101      101101十进制:     21          6           61          45对应编码:   V           G           9           t  

所以,btoa('Tom') = VG9t

b) 字符串长度不能被3整除时,比如“Lucy”:

            L           u           c           yASCII:      76          117         99          1218bit字节:   01001100    01110101    01100011    01111001      00000000    000000006bit字节:     010011      000111      010101      100011      011110  010000  000000  000000十进制:     19          7           21          35             30      16      (异常) (异常)      对应编码:   T           H           V           j               e       Q       =       =

由于Lucy只有4个字母,所以按3个一组的话,第二组还有两个空位,所以需要用0来补齐。这里就需要注意,因为是需要补齐而出现的0,所以转化成十进制的时候就不能按常规用base64编码表来对应,所以不是a, 可以理解成为一种特殊的“异常”,编码应该对应“=”。

有了上面的理论,那我们实现一个base64编码就容易了。

参考

http://blog.csdn.net/ishow99/article/details/5709274

以下经过IDE测试

// Base64.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <string>

static const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 
 
static inline bool is_base64(unsigned char c) 

    return (isalnum(c) || (c == '+') || (c == '/')); 

/*******************************************************************
函 数 名 称:  base64_encode
功 能 描 述:  Base64编码
参 数 说 明:  bytes_to_encode:    输入的BYTE流[in]
in_len:             字节长度[in]

返回值 说明:   编码后std::string
作       者:    huangjf
更 新 日 期:  2009.12.8
*******************************************************************/ 
std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) 

 std::string ret; 
 int i = 0; 
 int j = 0; 
 unsigned char char_array_3[3]; 
 unsigned char char_array_4[4]; 

 while (in_len--) 
 { 
  char_array_3[i++] = *(bytes_to_encode++); 
  if (i == 3) { 
   // 第一个6位只需要让8位二进制右移两位
   char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
   //第二个6位 = 第一个8位的后两位 + 第二个8位的前4位
   char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
   //第三个6位 = 第二个8位的后4位 + 第三个8位的前2位
   char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
   //第4个6位 = 第三个8位的后6位
   char_array_4[3] = char_array_3[2] & 0x3f; 

   for (i = 0; (i <4) ; i++) 
    ret += base64_chars[char_array_4[i]]; 
   i = 0; 
  } 
 } 

 if (i) 
 { 
  for (j = i; j < 3; j++) 
   char_array_3[j] = '/0'; 

  char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; 
  char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); 
  char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); 
  char_array_4[3] = char_array_3[2] & 0x3f; 

  for (j = 0; (j < i + 1); j++) 
   ret += base64_chars[char_array_4[j]]; 

  while ((i++ < 3)) 
   ret += '='; 

 } 

 return ret; 

/*******************************************************************
函 数 名 称:  base64_decode
功 能 描 述:  Base64解码
参 数 说 明:  encoded_string: 输入的BYTE流[in]

返回值 说明:   解码后std::string
作       者:    huangjf
更 新 日 期:  2009.12.8
*******************************************************************/ 
std::string base64_decode(std::string const& encoded_string) 

 int in_len = static_cast<int>(encoded_string.size()); 
 int i = 0; 
 int j = 0; 
 int in_ = 0; 
 unsigned char char_array_4[4], char_array_3[3]; 
 std::string ret; 

 while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) 
 { 
  char_array_4[i++] = encoded_string[in_]; 
  in_++; 
  if (i ==4) { 
   for (i = 0; i <4; i++) 
    char_array_4[i] = (unsigned char)base64_chars.find(char_array_4[i]); 

   char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); 
   char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); 
   char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; 

   for (i = 0; (i < 3); i++) 
    ret += char_array_3[i]; 
   i = 0; 
  } 
 } 

 if (i) { 
  for (j = i; j <4; j++) 
   char_array_4[j] = 0; 

  for (j = 0; j <4; j++) 
   char_array_4[j] = (unsigned char)base64_chars.find(char_array_4[j]); 

  char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); 
  char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); 
  char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; 

  for (j = 0; (j < i - 1); j++) ret += char_array_3[j]; 
 } 

 return ret; 
}

int _tmain(int argc, _TCHAR* argv[])
{
 //const std::string s = "ogmSJoDEG1HlCroMCthhGSR0cFGiUl/ES8ezkVSaRgktdzOR8O4hL1F6F7hT4uggKr24QfAi4etsrwVetAJCDOTk7s+o0l6ydpH2bCMby+4wtUMTF4U4dex/IjrmUreyFgv/4hbO0v0=" ;
 const std::string s = "abc";
 std::string encoded = base64_encode(reinterpret_cast<const unsigned char*>(s.c_str()), s.length());
 std::string decoded = base64_decode(encoded);

 std::cout << "encoded: " << encoded << std::endl;
 std::cout << "decoded: " << decoded << std::endl;

 return 0;

以下是我编译通过的源码:

 http://download.csdn.net/detail/lys07962000/6453227