BASE64编码规则及JAVA中的使用

BASE64编码规则及JAVA中的使用

一、编码规则:

Base64编码要求把3个8位字节(3*8=24)转化为4个6位的字节(4*6=24),之后在6位的前面补两个0,形成8位一个字节的形式。
例如字符串“张3” : 11010101 11000101 00110011 转换后: 00110101 00011100 00010100 00110011 用十进制表示即为:53 34 20 51
这个并不是最终的结果,还需要根据Base64的编码表查询出转换后的值。下面就是BASE64编码表:

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 (pad) =

14 O 31 f   48 w

15 P 32 g   49 x

16 Q 33 h   50 y

以上一共是64个编码(0-63),这也是Base64名称的由来,编码的编号对应的是得出的新字节的十进制值。因此,上例中字符串“张3”经过编码后就成了字符串“1iUz”了。

当代码量不是3的整数倍时,代码量/3的余数自然就是2或者1。转换的时候,结果不够6位的用0来补上相应的位置,之后再在6位的前面补两个0。转换完空出的结果就用就用“=”来补位。譬如结果若最后余下的为2个字节的“张”:
字符串“张” 11010101 HEX:D5 11000101 HEX:C5
00110101 00011100 00010100 十进制53 十进制34 十进制20 pad 字符’1’ 字符’i’ 字符’U’ 字符’=’
这样,最后的2个字节被整理成了“1iU=”。
同理,若原代码只剩下一个字节,那么将会添加两个“=”。只有这两种情况,所以,Base64的编码最多会在编码结尾有两个“=”

相关Java代码

public class myBase64 {  private static final char[] legalChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray();

    public static String encode(byte[] data) {        

int start = 0;        

int len = data.length;        

StringBuffer buf = new StringBuffer(data.length * 3 / 2);        

int end = len - 3;        

int i = start;        

int n = 0;        

while (i <= end) {            

int d = ((((int) data[i]) & 0x0ff) << 16)                    

| ((((int) data[i + 1]) & 0x0ff) << 8)                    

| (((int) data[i + 2]) & 0x0ff);            

buf.append(legalChars[(d >> 18) & 63]);            

buf.append(legalChars[(d >> 12) & 63]);            

buf.append(legalChars[(d >> 6) & 63]);            

buf.append(legalChars[d & 63]);            

i += 3;            

if (n++ >= 14) {                

n = 0;                

buf.append(" ");            

}        

}

        if (i == start + len - 2) {            

    int d = ((((int) data[i]) & 0x0ff) << 16)                    

        | ((((int) data[i + 1]) & 255) << 8);

            buf.append(legalChars[(d >> 18) & 63]);            

    buf.append(legalChars[(d >> 12) & 63]);

            buf.append(legalChars[(d >> 6) & 63]);

            buf.append("=");

        } else if (i == start + len - 1) {

            int d = (((int) data[i]) & 0x0ff) << 16;

            buf.append(legalChars[(d >> 18) & 63]);

            buf.append(legalChars[(d >> 12) & 63]);

            buf.append("==");         }

        return buf.toString();     }

 

    private static int decode(char c) {

     if (c >= 'A' && c <= 'Z')

            return ((int) c) - 65;

        else if (c >= 'a' && c <= 'z')

            return ((int) c) - 97 + 26;

        else if (c >= '0' && c <= '9')

            return ((int) c) - 48 + 26 + 26;

        else

            switch (c) {

            case '+':

                return 62;

            case '/':

                return 63;

            case '=':

                return 0;

            default:

       throw new RuntimeException("unexpected code: " + c);

            }

    }

    public static byte[] decode(String s) {

        ByteArrayOutputStream bos = new ByteArrayOutputStream();

        try {

            decode(s, bos);

        } catch (IOException e) {

            throw new RuntimeException();

        }

        byte[] decodedBytes = bos.toByteArray();

        try {

            bos.close();

            bos = null;

        } catch (IOException ex) {

            System.err.println("Error while decoding BASE64: " + ex.toString());

        }

        return decodedBytes;

    }

 

    private static void decode(String s, OutputStream os) throws IOException {

        int i = 0;

        int len = s.length();

        while (true) {

            while (i < len && s.charAt(i) <= ' ')

                i++;

            if (i == len)

                break;

            int tri = (decode(s.charAt(i)) << 18)

                    + (decode(s.charAt(i + 1)) << 12)

                    + (decode(s.charAt(i + 2)) << 6)

                    + (decode(s.charAt(i + 3)));

            os.write((tri >> 16) & 255);

            if (s.charAt(i + 2) == '=')

                break;

            os.write((tri >> 8) & 255);

            if (s.charAt(i + 3) == '=')

                break;

            os.write(tri & 255);

            i += 4;

        }

    }

}

posted on 2013-08-29 12:30  3G时代的码农工  阅读(464)  评论(0编辑  收藏  举报