class="java" name="code"> /** * 将三个8位二进制看成一组,转为4个6位二进制组,不足8位的补0, 转完后, 对应4个十进制数字, 然后可以查找base64编码表 * (六位二进制数对应的最小十进制数是0,最大十进制数是63, 因此base64码表一共包含64个字符)进行编码 * 如果要转的字符个数不是3的倍数,则需要相应的补= 一个字符,需要补两个= 两个字符,需要补一个= * * * * * 字符 A * ASCII码 65 * 二进制码 010000 01 * 4个6位二进制码 010000 010000 * 4个8位二进制码 00010000 00010000 * 十进制码 16 16 * 字符表映射码 Q Q == * * RFC2045还规定每行位76个字符,每行末尾需添加一个回车换行符,即便是最后一行不够76个字符,也要加换行符。 */ public class MyBase64 { private static char[] base64 = { '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', '+', '/' }; private static byte[] convert_base64 = new byte[127]; static { for (byte i = 0; i < base64.length; i++) { convert_base64[base64[i]] = i;// base64码表的值作为索引, 索引作为值 } } private static final int CHUNK_LENGTH = 76; private static final String CHUNK_SEPARATPR = System .getProperty("line.separator"); private static final String PAD = "="; public static byte[] decode(String base64Str) { char[] chs = base64Str.toCharArray(); int i = 0, validSize = 4; ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buf = new byte[4]; for (char c : chs) { if (c == '\r' || c == '\n') continue; if (c == '=') validSize--; else buf[i] = convert_base64[c]; if (++i == 4) { switch (validSize) { case 2: // 包含两个=, 只对应一个字节 baos.write(((buf[0] & 0x3F) << 2) | ((buf[1] & 0x30) >>> 4)); break; case 3: // 包含一个=, 对应两个个字节 baos.write(((buf[0] & 0x3F) << 2) | ((buf[1] & 0x30) >>> 4)); baos.write(((buf[1] & 0x0F) << 4) | ((buf[2] & 0x3C) >>> 2)); break; case 4: // 对应三个字节 baos.write(((buf[0] & 0x3F) << 2) | ((buf[1] & 0x30) >>> 4)); baos.write(((buf[1] & 0x0F) << 4) | ((buf[2] & 0x3C) >>> 2)); baos.write(((buf[2] & 0x03) << 6 | (buf[3] & 0x3F))); break; } i = 0; } } return baos.toByteArray(); } public static String encode(byte[] bytes, boolean isChunked) { int i = 0, lineSize = 0; byte[] buf = new byte[3]; StringBuilder base64Str = new StringBuilder(); for (byte b : bytes) { buf[i] = b; i++; // 如果存在第三个字符 if (i == 3) { // 取第一个字符的前面六位, 跟0XFC(1111 1100)按位与, 再右移两位 base64Str.append(base64[(buf[0] & 0xFC) >>> 2]); // 1. 取第一个字符的最后两位跟0X03(0000 0011)按位与, 左移四位 // 2. 取第二个字符的前面四位跟0XF0(1111 0000)按位与, 右移四位 // 3. 将第一步和第二步得到的结果做按位或, 得到六位二进制 base64Str.append(base64[((buf[0] & 0x03) << 4) | ((buf[1] & 0xF0) >>> 4)]); // 1. 取第二个字符的最后四位跟0X0F(0000 1111)按位与, 左移2位 // 2. 取第三个字符的前面两位跟0XC0(1100 0000)按位与, 右移六位 // 3. 将第一步和第二步得到的结果做按位或, 得到六位二进制 base64Str.append(base64[((buf[1] & 0x0F) << 2) | ((buf[2] & 0xC0) >>> 6)]); // 取第三个字符的最后六位跟0X3F(0011 1111)按位与 base64Str.append(base64[(buf[2] & 0x3F)]); lineSize += 4; if (lineSize >= CHUNK_LENGTH) { if (isChunked) base64Str.append(CHUNK_SEPARATPR); lineSize = 0; } i = 0; } } // 只有一个字符 if (i == 1) { base64Str.append(base64[(buf[0] & 0xFC) >>> 2]); base64Str.append(base64[(buf[0] & 0x03) << 4]); base64Str.append(PAD).append(PAD); lineSize += 2; } // 有两个字符 if (i == 2) { base64Str.append(base64[(buf[0] & 0xFC) >>> 2]); base64Str.append(base64[((buf[0] & 0x03) << 4) | ((buf[1] & 0xF0) >>> 4)]); base64Str.append(base64[(buf[1] & 0x0F) << 2]); base64Str.append(PAD); lineSize += 3; } if (lineSize > 0) { if (isChunked) base64Str.append(CHUNK_SEPARATPR); lineSize = 0; } return base64Str.toString(); } public static void main(String[] args) throws Exception { String s = "中华人民共和国 !!!24@#$@##&sdFSDF#@$@#$@#"; String result = encode(s.getBytes("UTF-8"), true); System.out.println(result); System.out.println(s); String str = "5Lit5Y2O5Lq65rCR5YWx5ZKM5Zu9ICEhITI0QCMkQCMjJnNkRlNERiNAJEAjJEAj\r\n"; byte[] bs = decode(str); System.out.println(bs.length); System.out.println(new String(bs, "UTF-8")); } private static void test_encode() throws UnsupportedEncodingException { String s = "abc"; boolean isChuncked = false; // String s = ""; // String s = "a"; // String s = "ab"; byte[] bytes = s.getBytes("UTF-8"); System.out.println("======================="); String result = encode(bytes, isChuncked); System.out.println(result); System.out.println("======================="); // base64.close(); System.out.println("======================="); byte[] newBytes = Base64.encodeBase64(bytes, isChuncked); System.out.println(new String(newBytes)); System.out.println("======================="); } }