Base64编码与解码实现
问题
java中import sun.misc.BASE64Decoder;提示如下错误:
Access restriction: The type BASE64Decoder is not accessible due to restriction on required library
解决方法
可以使用Tomcat6.0中的org.apache.tomcat.util.buf.Base64类。但由于org.apache.tomcat.util.buf.Base64不支持中文的转码,于是在其基础上稍作了一些修改,具体代码如下:
package com.ztools.mail; public class Base64 { static private final int BASELENGTH = 255; static private final int LOOKUPLENGTH = 64; static private final int TWENTYFOURBITGROUP = 24; static private final int EIGHTBIT = 8; static private final int SIXTEENBIT = 16; static private final int FOURBYTE = 4; static private final byte PAD = (byte) '='; static private byte[] base64Alphabet = new byte[BASELENGTH]; static private byte[] lookUpBase64Alphabet = new byte[LOOKUPLENGTH]; static private final boolean ISDEBUG = true; static { for (int i = 0; i < BASELENGTH; i++) { base64Alphabet[i] = -1; } // A-Z 0-25 for (int i = 'Z'; i >= 'A'; i--) { base64Alphabet[i] = (byte) (i - 'A'); } // a-z 26-51 for (int i = 'z'; i >= 'a'; i--) { base64Alphabet[i] = (byte) (i - 'a' + 26); } // 1-9 52-61 for (int i = '9'; i >= '0'; i--) { base64Alphabet[i] = (byte) (i - '0' + 52); } base64Alphabet['+'] = 62; base64Alphabet['/'] = 63; for (int i = 0; i <= 25; i++) lookUpBase64Alphabet[i] = (byte) ('A' + i); for (int i = 26, j = 0; i <= 51; i++, j++) lookUpBase64Alphabet[i] = (byte) ('a' + j); for (int i = 52, j = 0; i <= 61; i++, j++) lookUpBase64Alphabet[i] = (byte) ('0' + j); lookUpBase64Alphabet[62] = (byte) '+'; lookUpBase64Alphabet[63] = (byte) '/'; } static boolean isBase64(byte octect) { // shall we ignore white space? JEFF?? return (octect == PAD || base64Alphabet[octect] != -1); } static boolean isArrayByteBase64(byte[] arrayOctect) { int length = arrayOctect.length; if (length == 0) return false; for (int i = 0; i < length; i++) { if (Base64.isBase64(arrayOctect[i]) == false) return false; } return true; } /** * Encodes hex octects into Base64 * * @param binaryData * Array containing binaryData * @return Encoded Base64 array */ public static byte[] encode(byte[] binaryData) { int lengthDataBits = binaryData.length * EIGHTBIT; int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP; int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP; byte encodedData[] = null; if (fewerThan24bits != 0) // data not divisible by 24 bit encodedData = new byte[(numberTriplets + 1) * 4]; else // 16 or 8 bit encodedData = new byte[numberTriplets * 4]; byte k = 0, l = 0, oldByte1 = 0, oldByte2 = 0, oldByte3 = 0; int encodedIndex = 0; int dataIndex = 0; int i = 0; for (i = 0; i < numberTriplets; i++) { dataIndex = i * 3; oldByte1 = binaryData[dataIndex]; oldByte2 = binaryData[dataIndex + 1]; oldByte3 = binaryData[dataIndex + 2]; l = (byte) (oldByte2 & 0x0f); k = (byte) (oldByte1 & 0x03); // new bytes (three bytes to four bytes) encodedIndex = i * 4; encodedData[encodedIndex] = lookUpBase64Alphabet[oldByte1 >> 2 & 0x3f]; encodedData[encodedIndex + 1] = lookUpBase64Alphabet[(oldByte2 >> 4 & 0xf) | (k << 4)]; encodedData[encodedIndex + 2] = lookUpBase64Alphabet[(l << 2) | (oldByte3 >> 6 & 0x3)]; encodedData[encodedIndex + 3] = lookUpBase64Alphabet[oldByte3 & 0x3f]; } // form integral number of 6-bit groups dataIndex = i * 3; encodedIndex = i * 4; if (fewerThan24bits == EIGHTBIT) { oldByte1 = binaryData[dataIndex]; k = (byte) (oldByte1 & 0x03); encodedData[encodedIndex] = lookUpBase64Alphabet[oldByte1 >> 2 & 0x3f]; encodedData[encodedIndex + 1] = lookUpBase64Alphabet[k << 4]; encodedData[encodedIndex + 2] = PAD; encodedData[encodedIndex + 3] = PAD; } else if (fewerThan24bits == SIXTEENBIT) { oldByte1 = binaryData[dataIndex]; oldByte2 = binaryData[dataIndex + 1]; l = (byte) (oldByte2 & 0x0f); k = (byte) (oldByte1 & 0x03); encodedData[encodedIndex] = lookUpBase64Alphabet[oldByte1 >> 2 & 0x3f]; encodedData[encodedIndex + 1] = lookUpBase64Alphabet[(oldByte2 >> 4 & 0xf) | (k << 4)]; encodedData[encodedIndex + 2] = lookUpBase64Alphabet[l << 2]; encodedData[encodedIndex + 3] = PAD; } return encodedData; } public static String encode(String str) { byte[] binaryData = str.getBytes(); return new String(encode(binaryData)); } /** * Decodes Base64 data into octects * * @param base64Data * Byte array containing Base64 data * @return Array containind decoded data. */ public static byte[] decode(byte[] base64Data) { int numberQuadruple = base64Data.length / FOURBYTE; byte decodedData[] = null; byte b1 = 0, b2 = 0, b3 = 0, b4 = 0, marker0 = 0, marker1 = 0; // Throw away anything not in base64Data // Adjust size int encodedIndex = 0; int dataIndex = 0; decodedData = new byte[numberQuadruple * 3 + 1]; for (int i = 0; i < numberQuadruple; i++) { dataIndex = i * 4; marker0 = base64Data[dataIndex + 2]; marker1 = base64Data[dataIndex + 3]; b1 = base64Alphabet[base64Data[dataIndex]]; b2 = base64Alphabet[base64Data[dataIndex + 1]]; if (marker0 != PAD && marker1 != PAD) { // No PAD e.g 3cQl b3 = base64Alphabet[marker0]; b4 = base64Alphabet[marker1]; decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4); decodedData[encodedIndex + 1] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); decodedData[encodedIndex + 2] = (byte) (b3 << 6 | b4); } else if (marker0 == PAD) { // Two PAD e.g. 3c[Pad][Pad] decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4); decodedData[encodedIndex + 1] = (byte) ((b2 & 0xf) << 4); decodedData[encodedIndex + 2] = (byte) 0; } else if (marker1 == PAD) { // One PAD e.g. 3cQ[Pad] b3 = base64Alphabet[marker0]; decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4); decodedData[encodedIndex + 1] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); decodedData[encodedIndex + 2] = (byte) (b3 << 6); } encodedIndex += 3; } // NNN000 to NNN (clear end zero) int retDateLength = decodedData.length; for (int i = retDateLength - 1; i >= 0; i--) { if (0 != decodedData[i]) { break; } retDateLength--; } byte[] retDate = new byte[retDateLength]; System.arraycopy(decodedData, 0, retDate, 0, retDateLength); return retDate; } public static String decode(String base64String) { char[] cs = base64String.toCharArray(); byte[] bs = new byte[cs.length]; for (int i = 0; i < cs.length; i++) { bs[i] = (byte) cs[i]; } return new String(decode(bs)); } static final int base64[] = { 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64, 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64, 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 }; public static String base64Decode(String orig) { char chars[] = orig.toCharArray(); StringBuffer sb = new StringBuffer(); int i = 0; int shift = 0; // # of excess bits stored in accum int acc = 0; for (i = 0; i < chars.length; i++) { int v = base64[chars[i] & 0xFF]; if (v >= 64) { if (chars[i] != '=') if (ISDEBUG) System.out.println(("Wrong char in base64: " + chars[i])); } else { acc = (acc << 6) | v; shift += 6; if (shift >= 8) { shift -= 8; sb.append((char) ((acc >> shift) & 0xff)); } } } return sb.toString(); } }