Base64代码详解-编码注解

Base64概念参见

http://www.ruanyifeng.com/blog/2008/06/base64.html


用一句话来讲base64的话:

base64=64进制=用6位bit表示一个数字

2进制1位

8进制3位

16进制4位

64进制6位


base64编码的核心,就是将一个byte流用6bit的单位分割


科普完了,开始注解代码


 public static String encode(byte[] data, int off, int len) {

        if (len <= 0)  return "";

        char[] out = new char[len/3*4+4];//因为是8bit变成6bit,所以刚好3字节对应4个base64字符。所以有len/3*4 ,假设不能整除,至少会生成2个base64的字符,然后根据规范补上两个'=',所以后面+4. 如果是整除的情况,那么后面4个char是用不掉的  注解1

        int rindex = off;

        int windex = 0;//填充一个char,这里加1,刚好应对注解1整除的情况。

        int rest = len-off;

        while (rest >= 3) {

            // 3个字节作为1组处理

            int i = ((data[rindex]&0xff)<<16)

                    +((data[rindex+1]&0xff)<<8)

                    +(data[rindex+2]&0xff);

           /*

              假设这3字节的数据是 

               xxxxxxxx,xxxxxxxx,xxxxxxxx

              我们的目标是

              00xxxxxx,00xxxxxx,00xxxxxx,00xxxxxx


             step1:

             将3字节数据拼接到一块,想到的方法肯定是移位操作. 但是这里的数据有可能是1xxxxxxx这样的情况,移位的时候,会认为是负数,而直接在左边补1.这个是我们所

             不希望的。因此先将数据变成正的。所以先执行 byte&0xff.    

                                                                 xxxxxxxx

             00000000,00000000,00000000,11111111

             得到

             00000000,00000000,00000000,xxxxxxxx             

       

             然后通过左移操作得到(分别移动16,8位,然后&操作)

             00000000,xxxxxxxx,xxxxxxxx,xxxxxxxx

             这个数据和我们的目标数据

             00xxxxxx,00xxxxxx,00xxxxxx,00xxxxxx       

            还有点距离,但是回想,我们只需要分别得到6bit的数据,而不是他们拼接好的数据,因此我们可以通过移位分别得到预期的00xxxxxx数据。

            我要获取到第一个base64的编码

            00000000,aaaaaaaa,bbbbbbbb,cccccccc >>18;向右边移动18位,获取到00000000,00000000,00000000,00aaaaa      

            我要获取到第二个base64的编码

            00000000,aaaaaaaa,bbbbbbbb,cccccccc >>18;向右边移动12位,获取到00000000,00000000,0000aaaa,aaaabbbb,但是我们的预期是00aabbbb,因此我们需要把第6位后的数据置为0,通过&00000000, 00000000,00000000,00111111来得到。就有后面的&0x3f了。


            我要获取到第三个base64的编码

            同第2步操作,只是右移的位数不同


           我要获取到第4个base64的编码

           直接&,将第7位以及往左的高位全设为0


           然后通过获取到的编码,去对应的数字里将char值设置到目标数组就可以了。

           */

            out[windex++] = S_BASE64CHAR[i>>18];

            out[windex++] = S_BASE64CHAR[(i>>12)&0x3f];

            out[windex++] = S_BASE64CHAR[(i>>6)&0x3f];

            out[windex++] = S_BASE64CHAR[i&0x3f];

            rindex += 3;

            rest -= 3;

        }


       //下面是不能整除的情况,逻辑和上面差不多。


        if (rest == 1) {

            int i = data[rindex]&0xff;

            out[windex++] = S_BASE64CHAR[i>>2];

            out[windex++] = S_BASE64CHAR[(i<<4)&0x3f];

            out[windex++] = S_BASE64PAD;

            out[windex++] = S_BASE64PAD;

        } else if (rest == 2) {

            int i = ((data[rindex]&0xff)<<8)+(data[rindex+1]&0xff);

            out[windex++] = S_BASE64CHAR[i>>10];

            out[windex++] = S_BASE64CHAR[(i>>4)&0x3f];

            out[windex++] = S_BASE64CHAR[(i<<2)&0x3f];

            out[windex++] = S_BASE64PAD;

        }

        return new String(out, 0, windex);

    }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值