Base64编码说明:
Base64编码要求把3个8位字节(3*8=24)转化为4个6位的字节(4*6=24),之后在6位的前面补两个0,形成8位一个字节的形式。 如果剩下的字符不足3个字节,则用0填充,输出字符使用'=',因此编码后输出的文本末尾可能会出现1或2个'='。
为了保证所输出的编码位可读字符,Base64制定了一个编码表,以便进行统一转换。编码表的大小为2^6=64,这也是Base64名称的由来。
Base64编码表:
package com.sunchao.base64; /** * Base64 * @author Administrator * */ public class Base64 { private static final byte[] CODE; private static final int[] BI; static{ CODE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" .getBytes(); BI = new int['z' - '+' + 1]; for(int i = 0; i < CODE.length; i++) BI[CODE[i] - 1] = i; } private static final int indexOf(byte b){ int index = b - '+'; return BI[index]; } public static byte[] decode(byte[] base64){ if(base64 == null) throw new NullPointerException(); if(base64.length < 4) throw new IllegalArgumentException("invalid base64 format!"); int left = 0,right = (base64.length >> 2) * 3; int len = right; if(base64[base64.length-2] == '='){ len = right - 2; right = base64.length-3; }else if(base64[base64.length-1] == '='){ len = right - 1; right = base64.length-3; } final byte[] result = new byte[len]; for(int i=left,j=0;i<right&&j<len;){ int a = indexOf(base64[i++]); int b = indexOf(base64[i++]); int c = indexOf(base64[i++]); int d = indexOf(base64[i++]); byte aa = (byte)((a<<2)|((b>>4)&0xF)); byte bb = (byte)(((b & 0xf)<<4)|((c>>2)&0x3F)); byte cc = (byte)((c & 0x3)<<6 | d); result[j++] = aa; if(j >= len) break; result[j++] = bb; if(j >= len) break; result[j++] = cc; } return result; } public static byte[] encode(byte[] data, int offset, int len){ if(len == 0) return new byte[0]; checkBounds(data.length, offset, len); int lp3 = len % 3; final byte[] result; if(lp3 == 0) result = new byte[(len / 3) * 4]; else result = new byte[(len + 3 - lp3) / 3 * 4]; int left = offset, right = offset + len - lp3, i = 0; for(;left < right;){ byte a = data[left++]; byte b = data[left++]; byte c = data[left++]; i = encode(a, b, c, i, result); } if(lp3 >= 1){ int a = data[left++]; result[i++] = CODE[(a >> 2) & 0x3f]; int b = left<data.length?data[left++]:0; int c = left<data.length?data[left++]:0; result[i++] = CODE[(a & 3)<<4 | ((b>>4)&0xf)]; if(lp3 == 2) result[i++] = CODE[(b & 0xf)<<2 | ((c>>6)&0x3)]; else result[i++] = '='; result[i] = '='; } return result; } private static int encode(byte a, byte b, byte c, int i, byte[] result){ result[i++] = CODE[(a >> 2) & 0x3f]; result[i++] = CODE[(a & 3) << 4 | ((b>>4) & 0xf)]; result[i++] = CODE[(b & 0xf) << 2 | ((c>>6) & 0x3)]; result[i++] = CODE[c & 0x3f]; return i; } private static void checkBounds(int length, int offset, int charLen){ if(offset < 0) throw new IllegalArgumentException("Negative offset : " + offset); if(offset > length) throw new IndexOutOfBoundsException("offset over the length : " + (offset - length)); if(offset + charLen > length) throw new IndexOutOfBoundsException("offser + charLen - length : " + (offset + charLen - length)); } }