Base64要求把每三個8Bit的字節轉換爲四個6Bit的字節(3*8 = 4*6 = 24),然後把6Bit再添兩位高位0,組成四個8Bit的字節,也就是說,轉換後的字符串理論上將要比原來的長1/3。
這樣說會不會太抽象了?不怕,我們來看一個例子:
轉換前 aaaaaabb ccccdddd eeffffff
轉換後 00aaaaaa 00bbcccc 00ddddee 00ffffff
應該很清楚了吧?上面的三個字節是原文,下面的四個字節是轉換後的Base64編碼,其前兩位均爲0。
轉換後,我們用一個碼錶來得到我們想要的字符串(也就是最終的Base64編碼),這個表是這樣的:(摘自RFC2045)
Table 1: The Base64 Alphabet
Value Encoding Value Encoding Value Encoding Value Encoding
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 (pad) =
15 P 32 g 49 x
16 Q 33 h 50 y
讓我們再來看一個實際的例子,加深印象!
轉換前 10101101 10111010 01110110
轉換後 00101011 00011011 00101001 00110110
十進制 43 27 41 54
對應碼錶中的值 r b p 2
所以上面的24位編碼,編碼後的Base64值爲 rbp2
解碼同理,把 rbq2 的二進制位連接上再重組得到三個8位值,得出原碼。
(解碼只是編碼的逆過程,在此我就不多說了,另外有關MIME的RFC還是有很多的,如果需要詳細情況請自行查找。)
用更接近於編程的思維來說,編碼的過程是這樣的:
第一個字符通過右移2位獲得第一個目標字符的Base64表位置,根據這個數值取到表上相應的字符,就是第一個目標字符。
然後將第一個字符左移4位加上第二個字符右移4位,即獲得第二個目標字符。
再將第二個字符左移2位加上第三個字符右移6位,獲得第三個目標字符。
最後取第三個字符的右6位即獲得第四個目標字符。
在以上的每一個步驟之後,再把結果與 0x3F 進行 AND 位操作,就可以得到編碼後的字符了。
可是等等……聰明的你可能會問到,原文的字節數量應該是3的倍數啊,如果這個條件不能滿足的話,那該怎麼辦呢?
我們的解決辦法是這樣的:原文的字節不夠的地方可以用全0來補足,轉換時Base64編碼用=號來代替。這就是爲什麼有些Base64編碼會以一個或兩個等號結束的原因,但等號最多隻有兩個。因爲:
餘數 = 原文字節數 MOD 3
所以餘數任何情況下都只可能是0,1,2這三個數中的一個。如果餘數是0的話,就表示原文字節數正好是3的倍數(最理想的情況啦)。如果是1的話,爲了讓Base64編碼是4的倍數,就要補2個等號;同理,如果是2的話,就要補1個等號。
在線轉換:http://md5.mmkey.com/base64/
Java code
import sun.misc.BASE64Decoder;import sun.misc.BASE64Encoder;public class Test { public static void main(String args[]) throws IOException { BASE64Encoder encode = new BASE64Encoder(); String base64 = encode.encode("五筆字型電子計算機".getBytes());
System.out.println(base64); BASE64Decoder decode = new BASE64Decoder(); byte[] b = decode.decodeBuffer(base64); System.out.println(new String(b)); }}輸出:
zuWxytfW0M2159fTvMbL47v6
五筆字型電子計算機
JRE 中 sun 和 com.sun 開頭包的類都是未被文檔化的,他們屬於 java, javax
類庫的基礎,其中的實現大多數與底層平臺有關,一般來說是不推薦使用的。
Base64 主要不是加密,它主要的用途是把一些二進制數轉成普通字符用於網絡傳輸。
由於一些二進制字符在傳輸協議中屬於控制字符,不能直接傳送需要轉換一下就可以了。
// 將 s 進行 BASE64 編碼
public static String getBASE64(String s) {
if (s == null) return null;
return (new sun.misc.BASE64Encoder()).encode( s.getBytes() );
}
// 將 BASE64 編碼的字符串 s 進行解碼
public static String getFromBASE64(String s) {
if (s == null) return null;
BASE64Decoder decoder = new BASE64Decoder();
try {
byte[] b = decoder.decodeBuffer(s);
return new String(b);
} catch (Exception e) {
return null;
}
}