Base64编码要求把3个8位字节(3*8=24)转化为4个6位的字节(4*6=24),之后在6位的前面补两个0,形成8位一个字节的形式。 如果剩下的字符不足3个字节,则用0填充,输出字符使用'=',因此编码后输出的文本末尾可能会出现1或2个'='。

public class Base64Test {
    
    public static void main(String[] args) throws UnsupportedEncodingException {
        
        String str1 = "hello world";
        String str2 = "床前明月光,疑是地上霜,举头望明月,低头思故乡";
        String str3 = "好abcde";
        String str4 = "qwertyuiopasfghjklzxcvbnm";
        
        String r1 = toBase64(str1.getBytes("utf-8"));
        String r2 = toBase64(str2.getBytes("utf-8"));
        String r3 = toBase64(str3.getBytes("utf-8"));
        String r4 = toBase64(str4.getBytes("utf-8"));
        
        System.out.println(r1);
        System.out.println(r2);
        System.out.println(r3);
        System.out.println(r4);
        
        System.out.println("------------------------------------");
        // spring util
        System.out.println(Base64Utils.encodeToString(str1.getBytes("utf-8")));
        System.out.println(Base64Utils.encodeToString(str2.getBytes("utf-8")));
        System.out.println(Base64Utils.encodeToString(str3.getBytes("utf-8")));
        System.out.println(Base64Utils.encodeToString(str4.getBytes("utf-8")));
        
        System.out.println("------------------------------------");
        
        System.out.println(new String(base64Decode(r1),"utf-8"));
        System.out.println(new String(base64Decode(r2),"utf-8"));
        System.out.println(new String(base64Decode(r3),"utf-8"));
        System.out.println(new String(base64Decode(r4),"utf-8"));
    }
    
    
    
    public static String toBase64(byte[] bytes){
        char base64Char[] = {'A','B','C','D','E','F','G','H',
                             'I','J','K','L','M','N','O','P',
                             'Q','R','S','T','U','V','W','X',
                             'Y','Z','a','b','c','d','e','f',
                             'g','h','i','j','k','l','m','n',
                             'o','p','q','r','s','t','u','v',
                             'w','x','y','z','0','1','2','3',
                             '4','5','6','7','8','9','+','/'}; 
        byte b1,b2,b3;
        
        StringBuilder sb = new StringBuilder();
        
        for(int i=0;i<bytes.length;i+=3){
            
            b1 = bytes[i];
            sb.append(base64Char[(b1>>2&0x3f)]);
            if(i+1<bytes.length){
                b2 = bytes[i+1];
                sb.append(base64Char[(((b1<<4)|(b2>>4&0x0f))&0x3f)]);
                if(i+2<bytes.length){
                    b3 = bytes[i+2];
                    sb.append(base64Char[(((b2<<2)|(b3>>6&0x03))&0x3f)]);
                    sb.append(base64Char[(b3&0x3f)]);
                }else{
                    sb.append(base64Char[((b2<<2)&0x3C)]);
                    sb.append('=');
                }
                
            }else{
                sb.append(base64Char[((b1<<4)&0x30)]);
                sb.append('=');
                sb.append('=');
            }
        }
        return sb.toString();
    }
    
    public static byte[] base64Decode(String enCodeStr){
        
        int len;
        int index = enCodeStr.indexOf('=');
        if(index<0){
            len = enCodeStr.length()/4*3;
        }else{
            int subLen = enCodeStr.substring(index).length();
            if(subLen==1){
                len = enCodeStr.length()/4*3-1;
            }else{
                len = enCodeStr.length()/4*3-2;
            }
        }
        
        byte[] bytes = new byte[len];
        
        for(int i=0;i<enCodeStr.length()/4;i++){
            
            int a = getIntValue(enCodeStr.charAt(4*i));
            int b = getIntValue(enCodeStr.charAt(4*i+1));
            int c = getIntValue(enCodeStr.charAt(4*i+2));
            int d = getIntValue(enCodeStr.charAt(4*i+3));
            
            bytes[3*i]   = (byte) ((a<<2)|(b>>4&0x03));
            
            if(-1==c){// ==
                break;
            }else{
                bytes[3*i+1] = (byte) ((b<<4)|(c>>2&0x0f));
                
                if(-1==d){// =
                    break;
                }
            }
            bytes[3*i+2] = (byte) (c<<6|d);
        }
        
        return bytes;
    }

    
    public static int getIntValue(char c){
        
        switch(c){
            case 'A' : return 0;
            case 'B' : return 1;
            case 'C' : return 2;
            case 'D' : return 3;
            case 'E' : return 4;
            case 'F' : return 5;
            case 'G' : return 6;
            case 'H' : return 7;
            case 'I' : return 8;
            case 'J' : return 9;
            case 'K' : return 10;
            case 'L' : return 11;
            case 'M' : return 12;
            case 'N' : return 13;
            case 'O' : return 14;
            case 'P' : return 15;
            case 'Q' : return 16;
            case 'R' : return 17;
            case 'S' : return 18;
            case 'T' : return 19;
            case 'U' : return 20;
            case 'V' : return 21;
            case 'W' : return 22;
            case 'X' : return 23;
            case 'Y' : return 24;
            case 'Z' : return 25;
            case 'a' : return 26;
            case 'b' : return 27;
            case 'c' : return 28;
            case 'd' : return 29;
            case 'e' : return 30;
            case 'f' : return 31;
            case 'g' : return 32;
            case 'h' : return 33;
            case 'i' : return 34;
            case 'j' : return 35;
            case 'k' : return 36;
            case 'l' : return 37;
            case 'm' : return 38;
            case 'n' : return 39;
            case 'o' : return 40;
            case 'p' : return 41;
            case 'q' : return 42;
            case 'r' : return 43;
            case 's' : return 44;
            case 't' : return 45;
            case 'u' : return 46;
            case 'v' : return 47;
            case 'w' : return 48;
            case 'x' : return 49;
            case 'y' : return 50;
            case 'z' : return 51;
            case '0' : return 52;
            case '1' : return 53;
            case '2' : return 54;
            case '3' : return 55;
            case '4' : return 56;
            case '5' : return 57;
            case '6' : return 58;
            case '7' : return 59;
            case '8' : return 60;
            case '9' : return 61;
            case '+' : return 62;
            case '/' : return 63;
            case '=' : return -1;
            default : throw new RuntimeException("out of bound");
        }
    }
}