隨筆 - 312, 文章 - 14, 評(píng)論 - 1393, 引用 - 0
          數(shù)據(jù)加載中……

          Base64編碼原理與實(shí)現(xiàn)

          本文為原創(chuàng),如需轉(zhuǎn)載,請(qǐng)注明作者和出處,謝謝!

              Base64編碼的原理是按bit將每6個(gè)bit轉(zhuǎn)換成Base64編碼表中的相應(yīng)字符。下面是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

              在轉(zhuǎn)換到最后一個(gè)字節(jié)時(shí),可能出現(xiàn)如下兩種情況:
              1.  最后只剩下2個(gè)bit。
              2.  最后只剩下4個(gè)bit。
              對(duì)于這兩種情況,需要在后面補(bǔ)0,如下面的兩個(gè)字節(jié):
             
              11011001 11011101

              在轉(zhuǎn)換上面的字節(jié)時(shí),最后會(huì)剩下4個(gè)bit。也就是1101,這時(shí)需要在后面補(bǔ)0,也就是變成了110100。如果后面補(bǔ)一對(duì)0,轉(zhuǎn)換結(jié)果后面加一個(gè)“=”,如果補(bǔ)兩對(duì)0,加兩個(gè)“=”,也就是總共的bit數(shù)除3的余數(shù)為1,則加一個(gè)“=”,余數(shù)為2,加兩個(gè)“=”。上面的兩個(gè)字節(jié)是16個(gè)bit,除3的余數(shù)是1,因此,需要補(bǔ)一個(gè)“=”,也就是將這兩個(gè)字節(jié)分成如下三組:
             
              110110  011101  110100 

              其中110100后面兩個(gè)0是補(bǔ)的,因此,查找上面的base64編碼表可將這兩個(gè)字節(jié)轉(zhuǎn)換成如下的Base64編碼:

              2d0=

              下面我們來(lái)實(shí)現(xiàn)這個(gè)算法。算法的基本原理如下:

              由于每次轉(zhuǎn)換都需要6個(gè)bit,而這6個(gè)bit可能都來(lái)自一個(gè)字節(jié),也可以來(lái)自前后相臨的兩個(gè)字節(jié)。定義兩個(gè)變量:prevByteBitCount和nextByteBitCount,這兩個(gè)變量分別表述從前一個(gè)和后一個(gè)節(jié)字取得的bit數(shù)。如果prevByteBitCount為0,表示6個(gè)bit全部來(lái)自下一個(gè)字節(jié)的高6位。如果nextByteBitCount = 0,表示6個(gè)bit全部來(lái)自前一個(gè)字節(jié)的低6位。最后通過(guò)適當(dāng)?shù)囊莆猾@得所需要的6個(gè)bit,再在上面的base64編碼表中查找相應(yīng)的字符。算法的實(shí)現(xiàn)代碼如下:

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

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

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

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

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

              上面的代碼的執(zhí)行結(jié)果如下:

          5Lit5Y2O5Lq65rCR5YWx5ZKM5Zu9
          5Lit5Y2O5Lq65rCR5YWx5ZKM5Zu9




          Android開(kāi)發(fā)完全講義(第2版)(本書(shū)版權(quán)已輸出到臺(tái)灣)

          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) 評(píng)論(0)  編輯  收藏 所屬分類: java 、algorithm 、 原創(chuàng)

          主站蜘蛛池模板: 青铜峡市| 和硕县| 乌恰县| 长沙县| 肥乡县| 仁寿县| 平果县| 子洲县| 肇州县| 平顶山市| 彭山县| 聂荣县| 日土县| 广西| 西乌| 英超| 依兰县| 阜阳市| 乌拉特后旗| 高台县| 望谟县| 崇阳县| 青阳县| 玛曲县| 清镇市| 阿城市| 敖汉旗| 鄢陵县| 安图县| 天峨县| 务川| 盐源县| 教育| 周口市| 盐边县| 华池县| 四子王旗| 佳木斯市| 会理县| 内江市| 深圳市|