<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆 - 312, 文章 - 14, 評論 - 1393, 引用 - 0
    數據加載中……

    Base64編碼原理與實現

    本文為原創,如需轉載,請注明作者和出處,謝謝!

        Base64編碼的原理是按bit將每6個bit轉換成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
    15 P 32 g 49 x
    16 Q 33 h 50 y

        在轉換到最后一個字節時,可能出現如下兩種情況:
        1.  最后只剩下2個bit。
        2.  最后只剩下4個bit。
        對于這兩種情況,需要在后面補0,如下面的兩個字節:
       
        11011001 11011101

        在轉換上面的字節時,最后會剩下4個bit。也就是1101,這時需要在后面補0,也就是變成了110100。如果后面補一對0,轉換結果后面加一個“=”,如果補兩對0,加兩個“=”,也就是總共的bit數除3的余數為1,則加一個“=”,余數為2,加兩個“=”。上面的兩個字節是16個bit,除3的余數是1,因此,需要補一個“=”,也就是將這兩個字節分成如下三組:
       
        110110  011101  110100 

        其中110100后面兩個0是補的,因此,查找上面的base64編碼表可將這兩個字節轉換成如下的Base64編碼:

        2d0=

        下面我們來實現這個算法。算法的基本原理如下:

        由于每次轉換都需要6個bit,而這6個bit可能都來自一個字節,也可以來自前后相臨的兩個字節。定義兩個變量:prevByteBitCount和nextByteBitCount,這兩個變量分別表述從前一個和后一個節字取得的bit數。如果prevByteBitCount為0,表示6個bit全部來自下一個字節的高6位。如果nextByteBitCount = 0,表示6個bit全部來自前一個字節的低6位。最后通過適當的移位獲得所需要的6個bit,再在上面的base64編碼表中查找相應的字符。算法的實現代碼如下:

        public static String encoder(byte[] bytes)
        {
            StringBuilder result 
    = new StringBuilder();
            String base64 
    = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
            
    //  prevByteBitCount表示從前一個字節取得的bit數,nextByteBitCount表示從后一個字節取得的bit數
            int prevByteBitCount = 0, nextByteBitCount = 6;
            
    //  i表示當前的數組索引,n表示已經處理的位數
            int i = 0, n = 0;
            
    //  byteCount表示總的位數
            int byteCount = 8 * bytes.length;
            
    byte b = 0;
            
    while (true)
            {
                
    //  處理從前后兩個字節取得位數的情況
                if (prevByteBitCount > 0 && nextByteBitCount > 0)
                {
                    
    // 將前一個字節的低位向左移nextByteBitCount個bit,并使下一個字節的高位(nextByteBitCount指定的位數)右移到字節的最低位,
                    
    // 然后將兩個位移結果進行邏輯或,也就是將從前一個字節和后一個字節取得的相應的bit合并為一個字節的低位
                    b = (byte) (((0xff & bytes[i]) << nextByteBitCount) | ((0xff & bytes[i + 1]) >> (8 - nextByteBitCount)));
                    
    //  將邏輯或后的結果的最高兩個bit置成0
                    b = (byte) (b & 0x3f);
                    prevByteBitCount 
    = 8 - nextByteBitCount;
                    nextByteBitCount 
    = 6 - prevByteBitCount;
                }
                
    //  處理從后一個字節取得高6位的情況
                else if (prevByteBitCount == 0)
                {
                    
    //  后一個字節的高6位右移動低6位
                    b = (byte) ((0xff & bytes[i]) >> (8 - nextByteBitCount));
                    
    //  處理后面的位時,就是從前一個字節取2個bit,從后一個字字取4個bit
                    prevByteBitCount = 2;
                    nextByteBitCount 
    = 4;

                }
                
    //  處理從前一個字節取得低6位的情況
                else if (nextByteBitCount == 0)
                {
                    
    //  將前一個字節的最高兩個bit置成0
                    b = (byte) (0x3f & bytes[i]);
                    
    //  處理后面的位時,從后一個字節取6個bit
                    prevByteBitCount = 0;
                    nextByteBitCount 
    = 6;

                }
                result.append(base64.charAt(b));
                n 
    += 6;
                i 
    = n / 8;
                
    int remainBitCount = byteCount - n;
                
    if (remainBitCount < 6)
                {
                    
    //  將剩余的bit補0后,仍然需要在base64編碼表中查找相應的字符,并添加到結果字符串的最后
                    if (remainBitCount > 0)
                    {
                        b 
    = bytes[bytes.length - 1];
                        b 
    = (byte) (0x3f & (b << (6 - remainBitCount)));
                        result.append(base64.charAt(b));
                    }
                    
    break;
                }
            }
            
    //  如果總bit數除3的余數為1,加一個“=”,為2,加兩個“=”
            n = byteCount % 3;
            
    for (i = 0; i < n; i++)
                result.append(
    "=");

            
    return result.toString();
        }
     
        最后可以使用下面的代碼來驗證encoder方法的正確性:

        String s = "中華人民共和國";
       
    byte[] bytes = s.getBytes("UTF-8");
        System.out.println(encoder(bytes));
       
    //  使用jdk提供的base64轉換類對字節數組進行base64編碼
        sun.misc.BASE64Encoder base64Encoder = new sun.misc.BASE64Encoder();
        System.out.println(base64Encoder.encode(bytes));

        上面的代碼的執行結果如下:

    5Lit5Y2O5Lq65rCR5YWx5ZKM5Zu9
    5Lit5Y2O5Lq65rCR5YWx5ZKM5Zu9




    Android開發完全講義(第2版)(本書版權已輸出到臺灣)

    http://product.dangdang.com/product.aspx?product_id=22741502



    Android高薪之路:Android程序員面試寶典 http://book.360buy.com/10970314.html


    新浪微博:http://t.sina.com.cn/androidguy   昵稱:李寧_Lining

    posted on 2009-05-29 19:20 銀河使者 閱讀(4776) 評論(0)  編輯  收藏 所屬分類: javaalgorithm 原創

    主站蜘蛛池模板: 免费人成在线观看69式小视频| 亚洲an天堂an在线观看| 黄网站色在线视频免费观看| 成人免费av一区二区三区| 亚洲AV无码AV男人的天堂不卡| 亚洲成aⅴ人在线观看| 久久青青草原亚洲av无码| 国产一级淫片a免费播放口之| 在线a级毛片免费视频| 日本免费一区二区三区四区五六区| 一个人免费观看视频在线中文| 午夜亚洲WWW湿好爽| 日韩亚洲国产综合高清| 亚洲AV无码一区二区三区在线 | 黄色片网站在线免费观看| 中中文字幕亚洲无线码| 亚洲国产一区在线观看 | 久久久久久免费视频| 99视频精品全部免费观看| 国偷自产一区二区免费视频| a级大片免费观看| a级男女仿爱免费视频| a在线免费观看视频| a级毛片在线免费观看| 免费无码av片在线观看| 免费人成在线观看视频高潮| 丁香花在线视频观看免费| 永久免费不卡在线观看黄网站| 男女一进一出抽搐免费视频| 久久毛片免费看一区二区三区| 狠狠躁狠狠爱免费视频无码| 国产一级婬片A视频免费观看| 精品国产免费一区二区三区| 99久久成人国产精品免费| a级午夜毛片免费一区二区| 最新国产乱人伦偷精品免费网站 | 99久久精品国产亚洲| 亚洲欧洲日韩国产| 国产亚洲精aa在线看| 亚洲AV成人无码网站| 在线播放免费人成视频网站|