package com.qmth.cdut.supwisdom.utils; public abstract class Base64Utils { private static final byte[] ENC_TAB_BYTES = new byte[64]; static { int j = 0; for (byte i = 'A'; i <= 'Z'; i++) { ENC_TAB_BYTES[j] = i; j++; } for (byte i = 'a'; i <= 'z'; i++) { ENC_TAB_BYTES[j] = i; j++; } for (byte i = '0'; i <= '9'; i++) { ENC_TAB_BYTES[j] = i; j++; } ENC_TAB_BYTES[j++] = '+'; ENC_TAB_BYTES[j] = '/'; } public static String encodeBase64Str(String str) { byte[] bytes = StringUtils.getBytes(str); return encodeBase64Str(bytes); } public static String encodeBase64Str(byte[] bytes) { byte[] base64Bytes = encodeBase64(bytes); return StringUtils.newString(base64Bytes); } public static byte[] encodeBase64(byte[] bytes) { byte[] base64Bytes; int modulus = bytes.length % 3; if (modulus == 0) { base64Bytes = new byte[(4 * bytes.length) / 3]; } else { base64Bytes = new byte[4 * ((bytes.length / 3) + 1)]; } int dataLength = (bytes.length - modulus); int a1; int a2; int a3; for (int i = 0, j = 0; i < dataLength; i += 3, j += 4) { a1 = bytes[i] & 0xff; a2 = bytes[i + 1] & 0xff; a3 = bytes[i + 2] & 0xff; base64Bytes[j] = ENC_TAB_BYTES[(a1 >>> 2) & 0x3f]; base64Bytes[j + 1] = ENC_TAB_BYTES[((a1 << 4) | (a2 >>> 4)) & 0x3f]; base64Bytes[j + 2] = ENC_TAB_BYTES[((a2 << 2) | (a3 >>> 6)) & 0x3f]; base64Bytes[j + 3] = ENC_TAB_BYTES[a3 & 0x3f]; } int b1; int b2; int b3; int d1; int d2; switch (modulus) { case 0: break; case 1: d1 = bytes[bytes.length - 1] & 0xff; b1 = (d1 >>> 2) & 0x3f; b2 = (d1 << 4) & 0x3f; base64Bytes[base64Bytes.length - 4] = ENC_TAB_BYTES[b1]; base64Bytes[base64Bytes.length - 3] = ENC_TAB_BYTES[b2]; base64Bytes[base64Bytes.length - 2] = '='; base64Bytes[base64Bytes.length - 1] = '='; break; case 2: d1 = bytes[bytes.length - 2] & 0xff; d2 = bytes[bytes.length - 1] & 0xff; b1 = (d1 >>> 2) & 0x3f; b2 = ((d1 << 4) | (d2 >>> 4)) & 0x3f; b3 = (d2 << 2) & 0x3f; base64Bytes[base64Bytes.length - 4] = ENC_TAB_BYTES[b1]; base64Bytes[base64Bytes.length - 3] = ENC_TAB_BYTES[b2]; base64Bytes[base64Bytes.length - 2] = ENC_TAB_BYTES[b3]; base64Bytes[base64Bytes.length - 1] = '='; break; } return base64Bytes; } private static final byte[] DEC_TAB_BYTES = new byte[128]; static { for (int i = 0; i < 128; i++) { DEC_TAB_BYTES[i] = (byte) -1; } for (int i = 'A'; i <= 'Z'; i++) { DEC_TAB_BYTES[i] = (byte) (i - 'A'); } for (int i = 'a'; i <= 'z'; i++) { DEC_TAB_BYTES[i] = (byte) (i - 'a' + 26); } for (int i = '0'; i <= '9'; i++) { DEC_TAB_BYTES[i] = (byte) (i - '0' + 52); } DEC_TAB_BYTES['+'] = 62; DEC_TAB_BYTES['/'] = 63; } public static String decodeBase64Str(String data) { byte[] base64Bytes = StringUtils.getBytes(data); return decodeBase64Str(base64Bytes); } public static String decodeBase64Str(byte[] base64Bytes) { byte[] bytes = decodeBase64(base64Bytes); return StringUtils.newString(bytes); } public static byte[] decodeBase64(byte[] base64Bytes) { byte[] bytes; byte b1; byte b2; byte b3; byte b4; base64Bytes = discardNonBase64Bytes(base64Bytes); if (base64Bytes[base64Bytes.length - 2] == '=') { bytes = new byte[(((base64Bytes.length / 4) - 1) * 3) + 1]; } else if (base64Bytes[base64Bytes.length - 1] == '=') { bytes = new byte[(((base64Bytes.length / 4) - 1) * 3) + 2]; } else { bytes = new byte[((base64Bytes.length / 4) * 3)]; } for (int i = 0, j = 0; i < (base64Bytes.length - 4); i += 4, j += 3) { b1 = DEC_TAB_BYTES[base64Bytes[i]]; b2 = DEC_TAB_BYTES[base64Bytes[i + 1]]; b3 = DEC_TAB_BYTES[base64Bytes[i + 2]]; b4 = DEC_TAB_BYTES[base64Bytes[i + 3]]; bytes[j] = (byte) ((b1 << 2) | (b2 >> 4)); bytes[j + 1] = (byte) ((b2 << 4) | (b3 >> 2)); bytes[j + 2] = (byte) ((b3 << 6) | b4); } if (base64Bytes[base64Bytes.length - 2] == '=') { b1 = DEC_TAB_BYTES[base64Bytes[base64Bytes.length - 4]]; b2 = DEC_TAB_BYTES[base64Bytes[base64Bytes.length - 3]]; bytes[bytes.length - 1] = (byte) ((b1 << 2) | (b2 >> 4)); } else if (base64Bytes[base64Bytes.length - 1] == '=') { b1 = DEC_TAB_BYTES[base64Bytes[base64Bytes.length - 4]]; b2 = DEC_TAB_BYTES[base64Bytes[base64Bytes.length - 3]]; b3 = DEC_TAB_BYTES[base64Bytes[base64Bytes.length - 2]]; bytes[bytes.length - 2] = (byte) ((b1 << 2) | (b2 >> 4)); bytes[bytes.length - 1] = (byte) ((b2 << 4) | (b3 >> 2)); } else { b1 = DEC_TAB_BYTES[base64Bytes[base64Bytes.length - 4]]; b2 = DEC_TAB_BYTES[base64Bytes[base64Bytes.length - 3]]; b3 = DEC_TAB_BYTES[base64Bytes[base64Bytes.length - 2]]; b4 = DEC_TAB_BYTES[base64Bytes[base64Bytes.length - 1]]; bytes[bytes.length - 3] = (byte) ((b1 << 2) | (b2 >> 4)); bytes[bytes.length - 2] = (byte) ((b2 << 4) | (b3 >> 2)); bytes[bytes.length - 1] = (byte) ((b3 << 6) | b4); } return bytes; } private static byte[] discardNonBase64Bytes(byte[] datas) { byte[] temp = new byte[datas.length]; int bytesCopied = 0; for (byte data : datas) { if (isValidBase64Byte(data)) { temp[bytesCopied++] = data; } } byte[] newData = new byte[bytesCopied]; System.arraycopy(temp, 0, newData, 0, bytesCopied); return newData; } private static boolean isValidBase64Byte(byte b) { if (b == '=') { return true; } else if ((b < 0) || (b >= 128)) { return false; } else if (DEC_TAB_BYTES[b] == -1) { return false; } return true; } }