研究base64_encode的算法

 

 

 从网上看了一些资料,为了方便自己理解,于是把它的编码原理,自己放在excel表格中清晰列出来,方便以后查阅。做的图如下:

 

 

 

ascii编码表

 

这个表很大,截图不出来。网上有。0-255的整数表示256个字符,即2的8次方=256。2的7次方是128。

 参考:http://1024tools.com/ascii,图很清晰。

 

思考:base64编码算法,要求先去ascci表中对应字符的整数值。而ascci编码不支持中文的。从这个角度来看,base64_encode编码其实不支持中文编码的。具体中文编码后是什么情况,有待做一下试验后补充。

 

 

base64编码对应表

 

 

在程序中,用一个数组表示就是这样:

 

$base64_char = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';

 

比如整数24,那么就对应数组第25个元素:Y。

 

 

网上用的移位法,使用>>和<<,没有看明白怎么回事。根据编码的思路,拙劣地用php模拟实现了一个,对比一下与php内置的base64_encode()编码结果是不是一样

 

$string = 'abcde';

echo 'origin php 64 encode:';
var_dump(base64_encode($string));

function my_base64_encode($string = "") {
    $string_length = strlen($string);
//看余数
    $mod = $string_length % 3;
//echo 'mod:<br />';
//var_dump($mod);
    $add_bin_value = '';
    switch ($mod) {
        case 1:
            $add_bin_value = "0000000000000000";
            break;
        case 2:
            $add_bin_value = "00000000";
            break;
    }

    $group_count = ceil($string_length / 3); //得到多少组
//echo 'group <br />';
//var_dump($group_count);
    $string_arr = str_split($string, 1);
    $all_bin_value = '';
    foreach ($string_arr as $key => $value) {

        $ascii_int = ord($value); //得到这个字符在ascii表中的对应的10进制整数
        //然后把这个10进制整数,转换为二进制
        //echo '$ascii_int:' . $ascii_int . "<br />";

        $bin_value = decbin($ascii_int); //由于ascii的范围是0-255,如果是84,54这样比较小的值,这个函数会得到是一个1-7位的二进制。为了做到8位。于是增加判断一下,最高位要加0填充
        $str_len = strlen($bin_value);
        if ($str_len < 8) {
            $add_zero_count = 8 - $str_len; //要增加这么多个0在前面,以便补充8位
            for ($i = 0; $i < $add_zero_count; $i++) {
                $bin_value = '0' . $bin_value;
            }
        }
        //echo '$bin_value:' . $bin_value . "<br />";
        $all_bin_value.= $bin_value;
    }
    $all_bin_value = $all_bin_value . $add_bin_value;
    //var_dump($all_bin_value);
    $bin_group_list = str_split($all_bin_value, 6); //每6个二进制一组,进行分组
    //分组结果:
    //var_dump($bin_group_list);
    $base64_char = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
    $base64_char_arr = str_split($base64_char, 1);
//var_dump($base64_char_arr);
    $dec_int = 0;
    $base64_encode_result = '';
    foreach ($bin_group_list as $key => $value) {
        if ($value == '000000') {
            $base64_encode_result.='=';
        } else {
            $dec_int = bindec($value); //将二进制转换为10进制整数
            //echo $dec_int . "<br />";
            $base64_encode_result .= $base64_char_arr[$dec_int];
        }
    }
    
    return $base64_encode_result;
}


$base64_encode_result = my_base64_encode($string);
echo 'encode result:';
var_dump($base64_encode_result);
View Code

 

 

 

思考:

 

1、为什么要按照6位二进制一组进行分,而不是4位,7位等方式呢?

 

   因为要考虑到只有64个字符供选择,十进制只能从0到63。最大值63。使用6位,2的6次方,值是64。

   于是使用6位二进制的话,就能刚好对应出来。如果使用7位二进制。那么最大值是2的7次方,最大值是128。

   假设计算得到的是数字是112,那么base64编码表中如何去对应呢?

 

2、为什么要每三个字符为一组呢?不是2个,也不是4个字符一组。是什么考虑?

 

   不太清楚。尝试去分析一下,3个字符,,刚好是3*8=24位二进制。

 

  24个字符要分成6个二进制一组。就是4个组。

 

 

   2个字符呢,2*8=16  16/6也无法整除

 

   如果是4个字符一组,4*8=32个字符。32/6 无法整除。

 

   5个字符:5*8=40 40/6也无法整除。

 

   6个字符一组,6*8=48 48/6=8 刚好可以整除。怎么没用这个方式呢?

 

   应该是取小的原则。2个字符不可以,3个字符刚好可以。宁愿取小的。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

待完善

 

posted @ 2015-08-22 11:33  王滔  阅读(466)  评论(0编辑  收藏  举报