游戏开发论坛

 找回密码
 立即注册
搜索
查看: 1056|回复: 0

Base64的编解码方法 wxh zt

[复制链接]

1367

主题

1993

帖子

2118

积分

金牌会员

Rank: 6Rank: 6

积分
2118
发表于 2008-12-16 19:35:00 | 显示全部楼层 |阅读模式
作者:吴 巨强
    Base64是一种很 常用的编码方式,利用它可以将任何二进制的字符编 码到可打印的64个字符之中, 这样,不管是图片,中文文本等都可以编码 成只有ASCII的纯文本。至于为什么要进行这个转换呢 , 最初主要使用在EMail领域,早期的一些邮件网关 只识别ASCII, 如果发现邮件里有其他字符,就会将它们过 滤掉,这样中文的邮件,有图片附件的邮件在这些网 关上 就会发生问题,于是将中文和图片都使用base64 编码然后传输,接受后再解码就客服了这个问题了。 Base64除了可以使用在相似场合,还可以用 作简单的加密等等。下面介绍下Base64的方法:

    首先是Base64中 可能出现的所有字符:

  0 A        17 R        34 i        51 z
  1 B        18 S        35 j        52 0
  2 C        19 T        36 k        53 1
  3 D        20 U        37 l        54 2
  4 E        21 V        38 m        55 3
  5 F        22 W        39 n        56 4
  6 G        23 X        40 o        57 5
  7 H        24 Y        41 p        58 6
  8 I        25 Z        42 q        59 7
  9 J        26 a        43 r        60 8
  10 K       27 b        44 s        61 9
  11 L       28 c        45 t        62 +
  12 M       29 d        46 u        63 /
  13 N       30 e        47 v
  14 O       31 f        48 w        (pad) =
  15 P       32 g        49 x
  16 Q       33 h        50 y

    所有的字符就 是'A'~'Z','a'~'z','0'~'9','+','/'共64个,以及末 尾的填充字符'='

    编码的方法是:

    从输入缓冲中依 次取出字符,第一个字符的,从最高位开始取出6个 bit,这6个bit的值的范围在0~63,将这个值作为索引 , 对应上面的表格,找到相应的字符,这便是 第一个Base64后的字符,然后将第一个字符的低2位与 第二个字符的高4位组成6个bit, 同样查表得到第二个 Base64字符,以此类推,从左向右没凑足6个bit就转 换成一个Base64字符,由于输入缓冲中每3个字符 包含24个bit,这24个bit正好可以转成4个 Base64字符,所以没3个字符能组成一个转换循环,如 果输入缓冲中字符的个数是3 的整数倍,那么结果就 是4的整数倍,两者的长度是3:4的关系,但是如果输 入字符不是3的整数倍呢?这就涉及到了末尾填充问题 。

    输入缓冲的末尾 可能余下一个字符,或两个字符:

    如果余下一个字 符,前6个bit转换成Base64,剩下的低2位要右边补0 ,凑成6bit,然后转换成Base64,为了让解析者了解 这个 情况,在输出缓冲的最后要补上两个'='。
如果余下两个字符,同样转换出两个Base64 字符后,在剩下的4个bit右边补0,凑成6bit,然后转 换成Base64,同样在输出缓冲 的末尾要补上一个'=' 。
    由此可见Base64 后的字符串,长度一定是4的整数倍,末尾有一个,两 个或没有'='。
要注意的是为了兼容有些邮件服务器, Base64后的字符串经常要插入来确保每一行 不超过76个字符,解析时要跳过它们。

    好了,原理就是 这样的,是不是很简单,就是取3个转成4个,好了, 上代码:

    首先是编码:



              const BYTE Base64ValTab[65] =

"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrst

uvwxyz0123456789+/";

        #define AVal(x) Base64ValTab[x]
              int CSeeBase64Dlg::EncodeBase64(char *

pInput, char * pOutput)
        {
                int i = 0;
                int loop = 0;
                int remain = 0;
                int iDstLen = 0;
                int iSrcLen = (int)strlen

(pInput);
       
                loop = iSrcLen/3;
                remain = iSrcLen%3;
       
                // also can encode native char

one by one as decode method
                // but because all of char in

native string  is to be encoded so encode 3-

chars one time is easier.
       
                for (i=0; i < loop; i++)
                {
                        BYTE a1 = (pInput[i*3]

>> 2);
                        BYTE a2 = ( ((pInput

[i*3] & 0x03) << 4) | (pInput[i*3+1] >> 4) );
                        BYTE a3 = ( ((pInput

[i*3+1] & 0x0F) << 2) | ((pInput[i*3+2] & 0xC0)

>> 6) );
                        BYTE a4 = (pInput

[i*3+2] & 0x3F);
       
                        pOutput[i*4] = AVal

(a1);
                        pOutput[i*4+1] = AVal

(a2);
                        pOutput[i*4+2] = AVal

(a3);
                        pOutput[i*4+3] = AVal

(a4);
                }
       
                iDstLen = i*4;
       
                if (remain == 1)
                {
                        // should pad two equal

sign
                        i = iSrcLen-1;
                        BYTE a1 = (pInput >>

2);
                        BYTE a2 = ((pInput &

0x03) << 4);
                       
                        pOutput[iDstLen++] =

AVal(a1);
                        pOutput[iDstLen++] =

AVal(a2);
                        pOutput[iDstLen++] =

'=';
                        pOutput[iDstLen++] =

'=';
                        pOutput[iDstLen] =

0x00;
                }
                else if (remain == 2)
                {
                        // should pad one equal

sign
                        i = iSrcLen-2;
                        BYTE a1 = (pInput >>

2);
                        BYTE a2 = ( ((pInput

& 0x03) << 4) | (pInput[i+1] >> 4));
                        BYTE a3 = ( (pInput

[i+1] & 0x0F) << 2);
       
                        pOutput[iDstLen++] =

AVal(a1);
                        pOutput[iDstLen++] =

AVal(a2);
                        pOutput[iDstLen++] =

AVal(a3);
                        pOutput[iDstLen++] =

'=';
                        pOutput[iDstLen] =

0x00;
                }
                else
                {
                        // just division by 3
                        pOutput[iDstLen] =

0x00;
                }
       
                return iDstLen;
}
      


    下面是解析的:


        const BYTE Base64IdxTab[128] =
        {
        255,255,255,255,  255,255,255,255,  

255,255,255,255,  255,255,255,255,
        255,255,255,255,  255,255,255,255,  

255,255,255,255,  255,255,255,255,
        255,255,255,255,  255,255,255,255,  

255,255,255,62,   255,255,255,63,
        52,53,54,55,      56,57,58,59,      

60,61,255,255,    255,255,255,255,
        255,0,1,2,        3,4,5,6,         

7,8,9,10,         11,12,13,14,
        15,16,17,18,      19,20,21,22,      

23,24,25,255,     255,255,255,255,
        255,26,27,28,     29,30,31,32,      

33,34,35,36,      37,38,39,40,
        41,42,43,44,      45,46,47,48,      

49,50,51,255,     255,255,255,255
        };

        #define BVal(x) Base64IdxTab[x]

        int CSeeBase64Dlg:ecodeBase64(char *

pInput, char * pOutput)
        {
                int i = 0;
                int iCnt = 0;
                int iSrcLen = (int)strlen

(pInput);
       
                char * p = pOutput;
       
                for (i=0; i < iSrcLen; i++)
                {
                        if (pInput > 127)

continue;
                        if (pInput == '=')

return p-pOutput+1;
       
                        BYTE a = BVal(pInput

);
                        if (a == 255) continue;
                       
                        switch (iCnt)
                        {
                        case 0:
                                {
                                        *p = a

<< 2;
                                        iCnt++;
                                }
                                break;
       
                        case 1:
                                {
                                        *p++ |=

a >> 4;
                                        *p = a

<< 4;
                                        iCnt++;
                                }
                                break;
       
                        case 2:
                                {
                                        *p++ |=

a >> 2;
                                        *p = a

<< 6;
                                        iCnt++;
                                }
                                break;
       
                        case 3:
                                {
                                        *p++ |=

a;
                                        iCnt =

0;
                                }
                                break;
                        }
                }
       
                *p = 0x00;
                return p-pOutput;
        }

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2026-1-20 17:07

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表