不仅仅是实现base64工具类
虽然在jmh上测试性能比jdk自带的差点,但是可以通过 实现 接口 Coding 来实现一种 类base64 新的编码方式。(这点很有用,等于是base64加强实现)
当然你也可以直接参考jdk的 encode0 和 decode0 来实现更优的。
package my.code; public class Base64Plus { private static final int BIT = 0x3F; private static final int BIT6 = BIT << 6; private static final int BIT12 = BIT << 12; private static final int BIT18 = BIT << 18; /** * 这里如果使用原生数组,不使用条件判断,估计能和jdk原生的性能相当。 * jdk的实现思路: intToChar 64的数组实现,charToByte 256(ASCII码的长度)的数组(下标:ascii码对应整数,值:对应的原数据)实现, */ public static final Coding BASE64 = new Coding() { @Override public char intToChar(int n) { if(n < 26) { return (char) (n + 65); } else if(n < 52) { return (char) (n + 71); } else if(n < 62) { return (char) (n - 4); } else if(n == 62) { return '+'; } else if(n == 63) { return '/'; } return '='; } @Override public byte charToByte(char n) { if(n >= 'A' && n <= 'Z') { return (byte) (n - 65); } else if(n >= 'a' && n <= 'z') { return (byte) (n - 71); } else if(n >= '0' && n <= '9') { return (byte) (n + 4); } else if(n == '+') { return 62; } else if(n == '/') { return 63; } throw new RuntimeException("不是base64的字符: " + n); } }; public static final Coding MyCoding = new Coding() { @Override public char intToChar(int n) { if(n < 10) { return (char) (n + 48); } else if(n < 36) { return (char) (n + 55); } else if(n < 62) { return (char) (n + 61); } else if(n == 62) { return '+'; } else if(n == 63) { return '/'; } return '='; } @Override public byte charToByte(char n) { if(n >= 'A' && n <= 'Z') { return (byte) (n - 55); } else if(n >= 'a' && n <= 'z') { return (byte) (n - 61); } else if(n >= '0' && n <= '9') { return (byte) (n - 48); } else if(n == '+') { return 62; } else if(n == '/') { return 63; } throw new RuntimeException("不是base64的字符: " + n); } }; private final Coding coding; private final char end; public Base64Plus() { coding = BASE64; end = '='; } public Base64Plus(Coding coding) { this.coding = coding; end = '='; } public Base64Plus(Coding coding, char end) { this.coding = coding; this.end = end; } private static int toInt(byte a, byte b, byte c) { return ((a & 0xFF) << 16) + ((b & 0xFF) << 8) + (c & 0xFF); } private void intConvertChars(int n, char[] c, int start) { c[start] = coding.intToChar((n & BIT18) >> 18); c[start+1] = coding.intToChar((n & BIT12) >> 12); c[start+2] = coding.intToChar((n & BIT6) >> 6); c[start+3] = coding.intToChar(n & BIT); } private static int getCharSize(int len, int s) { switch (s) { case 1: return (len * 4) / 3 + 3; case 2: return (len * 4) / 3 + 2; default: return (len * 4) / 3; } } private static int getByteSize(int len, int flag) { switch (flag) { case 1: return (len * 3) / 4 - 1; case 2: return (len * 3) / 4 - 2; default: return (len * 3) / 4; } } public char[] encoding(byte [] data) { int l; if(data == null || (l = data.length) == 0) { return new char[0]; } int s = l % 3; int cyc = (l / 3) * 3; char [] c = new char[getCharSize(l, s)]; int start = 0; for(int i = 0;i < cyc;i+=3,start+=4) { intConvertChars(toInt(data[i], data[i+1], data[i+2]), c, start); } if(s == 1) { intConvertChars(toInt(data[l-1], (byte) 0, (byte) 0), c, start); c[c.length - 2] = c[c.length - 1] = end; } else if(s == 2) { intConvertChars(toInt(data[l-2], data[l-1], (byte) 0), c, start); c[c.length - 1] = end; } return c; } private int getFlag(char a, char b) { if(a != end && b != end) { return 0; } if(a == end && b == end) { return 2; } return 1; } public byte[] decoding(char [] data) { int l; if(data == null || (l = data.length) < 1) { return new byte[0]; } int start = 0; int flag = getFlag(data[l-1], data[l-2]); int cyc = flag == 0 ? (l / 4) * 4 : (l / 4 - 1) * 4; byte[] result = new byte[getByteSize(l, flag)]; for(int i = 0;i < cyc;i+=4,start+=3) { byte a = coding.charToByte(data[i]); byte b = coding.charToByte(data[i + 1]); byte c = coding.charToByte(data[i + 2]); byte d = coding.charToByte(data[i + 3]); int t = ((a << 18) & BIT18) + ((b << 12) & BIT12) + ((c << 6) & BIT6) + (d & BIT); result[start] = (byte) ((t & 0xff0000) >> 16); result[start+1] = (byte) ((t & 0x00ff00) >> 8); result[start+2] = (byte) (t & 0xff); } if(flag == 1) { byte a = coding.charToByte(data[l - 4]); byte b = coding.charToByte(data[l - 3]); byte c = coding.charToByte(data[l - 2]); int t = (((a & 0xFF) << 12) + ((b & 0xFF) << 6) + c) >> 2; result[result.length - 2] = (byte) ((t & 0xFF00) >> 8); result[result.length - 1] = (byte) (t & 0xFF); } else if(flag == 2) { byte a = coding.charToByte(data[l - 4]); byte b = coding.charToByte(data[l - 3]); result[result.length - 1] = (byte) ((((a & 0xFF) << 6) + (b & 0xFF)) >> 4); } return result; } /** * 接口必须要通过下面程序测试,才能使用 * Base64Plus.Coding coding = new 自己的实现类; * for(int i = 0;i < 64;i++) { * char t = coding.intToChar(i); * byte a = coding.charToByte(t); * if(a != i) { * throw new RuntimeException(i + " " + t + " " + a); * } * } */ public interface Coding { /** * @param n (0 =< n < 64) * @return */ char intToChar(int n); /** * @param n * @return (0 =< return < 64) */ byte charToByte(char n); } }
浙公网安备 33010602011771号