隨筆 - 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 銀河使者 閱讀(4778) 評論(0)  編輯  收藏 所屬分類: javaalgorithm 原創

          主站蜘蛛池模板: 太和县| 婺源县| 和硕县| 会东县| 汕尾市| 万全县| 吉首市| 基隆市| 宜城市| 泸水县| 永靖县| 元氏县| 剑阁县| 德昌县| 韶关市| 博罗县| 新邵县| 水城县| 凯里市| 封丘县| 梨树县| 沧源| 新邵县| 沙雅县| 兴化市| 砚山县| 中超| 枣庄市| 嘉禾县| 云梦县| 裕民县| 朝阳县| 北流市| 新竹市| 广宗县| 长丰县| 德阳市| 满洲里市| 耒阳市| 丰原市| 芜湖市|