package base64;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.FilterInputStream;import java.io.FilterOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.OutputStream;import java.io.Serializable;/** * Base64是MIME邮件中常用的编码之一。 * 编码方法:从输入数据流中每次取6bit, 将此6bit的值(0~63)作为索引去查表,输出相应字符。 * 每3个字节将编码为4个字符(3x8=4x6);不满4个字符的以‘=’填充 */@SuppressWarnings("unused")public class Base64 {public static final boolean ENCODE = true;//加密 public static final boolean DECODE = false;//触密 private static final int MAX_LINE_LENGTH = 76;//每行最大字符数 private static final byte EQUALS_SIGN = 61;//== private static final byte NEW_LINE = 10;private static final byte BAD_ENCODING = -9;//退格 private static final byte WHITE_SPACE_ENC = -5;//空格 private static final byte EQUALS_SIGN_ENC = -1;//== private static final byte ALPHABET[] = { 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47 }; private static final byte DECODABET[] = { -9, -9, -9, -9, -9, -9, -9, -9, -9, -5, -5, -9, -9, -5, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -5, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 62, -9, -9, -9, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -9, -9, -9, -1, -9, -9, -9, 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, -9, -9, -9, -9, -9, -9, 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, -9, -9, -9, -9 }; /** * 读取Base64编码的数 */public static class InStream extends FilterInputStream {private boolean encode;//是否编码private int position;//buffer中的位置private byte[] buffer;//保存转换后的数据private int bufferLength;//buffer的长度(3或4)private int numSigBytes;//buffer中有效字节的长度private int lineLength;//一行的字符数private boolean breakLines;//是否换行/** * 构造一个解码模式的类对象 */public InStream(InputStream in) {this(in, Base64.ENCODE);}/** * 根据encode参数判断该对象采用的模式 */public InStream(InputStream in, boolean encode) {this(in, encode, true);}/** * breakLines参数限定每行字符数 */public InStream(InputStream in, boolean encode, boolean breakLines) {super(in);this.breakLines = breakLines;this.encode = encode;this.bufferLength = encode ? 4 : 3;this.buffer = new byte[bufferLength];this.position = -1;this.lineLength = 0;}/** * 从输入流读取足够的数据进行Base64规范的编码或解码,并且返回下一个字节 */public int read() throws IOException {if(position < 0) {//如果数据不存在if(encode) {byte[] b3 = new byte[3];int numBinaryBytes = 0;for(int i=0; i<3; i++) {//编码,读取3个字节int b = in.read();if(b >= 0) {//判断是否到流的末尾b3[i] = (byte)b;numBinaryBytes++;}}if(numBinaryBytes > 0) {encode3to4(b3, 0, numBinaryBytes, buffer, 0);position = 0;numSigBytes = 4;} else {return -1;}} else {byte[] b4 = new byte[4];int i = 0;for(i=0; i<4; i++) {//解码,读取4个有效字节int b = 0;do{ b=in.read();}while(b >= 0 && DECODABET[b & 0x7f] <= WHITE_SPACE_ENC);if(b < 0) break;b4[i] = (byte)b;}if(i == 4) {numSigBytes = decode4to3(b4, 0, buffer, 0);position = 0;} else if(i == 0) {return -1;} else {throw new IOException("无效数据");}}} if(position >= 0) {//数据已存在,读取数据if(position >= numSigBytes) return -1;if(encode && breakLines && lineLength >= MAX_LINE_LENGTH) {//判断数据是否超过限长lineLength = 0;return '\n';} else {lineLength ++;int b = buffer[position++];if(position >= bufferLength) position = -1;return b & 0xFF;//将字节转换为unsigned类型}} else {throw new IOException("无效数据");}}/** * 读取数据,直至已经读取了len个字节或流的结束 */public int read(byte[] dest, int off, int len) throws IOException {int i,b;for(i=0; i<len; i++) {b = read();if(b >= 0)dest[off + i] = (byte)b;else if(i == 0) return -1;else break;}return i;}}/** * 按照Base64编码输出数据 */public static class OutStream extends FilterOutputStream {private boolean encode;private int position;private byte[] buffer;private int bufferLength;private int lineLength;private boolean breakLines;/** * 构造一个编码的输出流类对象 */public OutStream(OutputStream out) {this(out, Base64.ENCODE);}/** * 根据encode参数判断该类对象是编码模式还是解码模式 */public OutStream(OutputStream out, boolean encode) {this(out, encode, true);}/** * breakLines参数限定每行字符数 */public OutStream(OutputStream out, boolean encode, boolean breakLines) {super(out);this.breakLines = breakLines;this.encode = encode;this.bufferLength = encode ? 3 : 4;this.buffer = new byte[bufferLength];this.position = 0;this.lineLength = 0;}/** * 转化完成后,将字节定入输出流 * 如果是编码,则对字节进行缓存,每次缓存3个字节,然后执行写操作 * 如果是解码,则每次缓存4个字节 */public void write(int theByte) throws IOException {if(encode) {buffer[position++] = (byte)theByte;if(position >= bufferLength) {out.write(Base64.encode3to4(buffer, bufferLength));lineLength +=4;if(breakLines && lineLength >= MAX_LINE_LENGTH) {out.write(NEW_LINE);lineLength = 0;}position = 0;}} else {if(DECODABET[theByte & 0x7f] > WHITE_SPACE_ENC) {buffer[position++] = (byte)theByte;if(position >= bufferLength) {out.write(Base64.decode4to3(buffer));position = 0;}} else if(DECODABET[theByte & 0x7f] != WHITE_SPACE_ENC) {throw new IOException("无效数据");}}}/** * 写入len个字节 */public void write(byte[] theBytes, int off, int len) throws IOException {for(int i=0; i<len; i++) {write(theBytes[off + i]);}}/** * 编码时,对其进行补位; * 解码时,如果Base64规范的输入没有正确补位将会抛异常 */public void flush() throws IOException {if(out != null) super.flush();if(position > 0) {if(encode) {out.write(Base64.encode3to4(buffer, position));position = 0;} else {throw new IOException("无效数据");}}if(out != null)out.flush();}/** * 关闭并清空流 */public void close() throws IOException {if(out != null) {super.close();out.close();buffer = null;out = null;}}}/** * 对threeBytes数组的前3个字节进行编码,并且返回一个Base64规范的4-byte数组 */private static byte[] encode3to4(byte[] threeBytes) {return encode3to4(threeBytes, 3);}/** * threeBytes数组大小与numSigBytes相等 */private static byte[] encode3to4(byte[] threeBytes, int numSigBytes) {byte[] dest = new byte[4];encode3to4(threeBytes, 0, numSigBytes, dest, 0);return dest;}/** * 对source数组按照Base64规范进行编码,并将结果写入destination数组 * srcOffset和destOffset确定数组起点 * source数组大小必须满足srcOffset+3, destination数组大小必须满足destOffset+4 * numSigBytes指定数组中的实际有效字节数 */private static byte[] encode3to4(byte[] source, int srcOffset, int numSigBytes, byte[] destination, int destOffset) {/* * 如果numSigBytes是1或2就创建一个用0初始化的buffer,并且向左移动24位; * (其目的是为了将1完全清除,防止java在将一个字节转化成int型的时候,将值转化成负数) * * 1、左移运算符<<使指定值的所有位都左移规定的次数,规则: * 丢弃最高位,0补最低位; * 如果移动的位数超过了该类型的最大位数,那么编译器会对移动的位数取模 * 2、右移运算符>>使指定值的所有位都右移规定的次数,规则: * 符号位不变,左边补上符号位; * 3、无符号右移运算符>>>:忽略了符号位扩展,0补最高位 ;只是对32位和64位的值有意义 * 右移相当于除,左移相当于乘,左移一位乘2,左移二位乘4。。。 */int inBuff = (numSigBytes > 0 ? ((source[srcOffset] << 24) >>> 8) : 0) | (numSigBytes > 1 ? ((source[srcOffset + 1] << 24) >>> 16) : 0) |(numSigBytes > 2 ? ((source[srcOffset + 2] << 24) >>> 24) : 0);//根据有效的字节数进行转换switch(numSigBytes) {case 3:destination[destOffset] = ALPHABET[(inBuff >>> 18)];destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f];destination[destOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3f];destination[destOffset + 3] = ALPHABET[(inBuff) & 0x3f];return destination;case 2:destination[destOffset] = ALPHABET[(inBuff >>> 18)];destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f];destination[destOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3f];destination[destOffset + 3] = EQUALS_SIGN;return destination;case 1:destination[destOffset] = ALPHABET[(inBuff >>> 18)];destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f];destination[destOffset + 2] = EQUALS_SIGN;destination[destOffset + 3] = EQUALS_SIGN;return destination;default: return destination; }}/** * 对字节数组进行编码 */public static String encodeBytes(byte[] source) {return encodeBytes(source, true);}/** * 对字节数组进行编码 */public static String encodeBytes(byte[] source, boolean breakLines) {return encodeBytes(source, 0, source.length, breakLines);}/** * 对字节数组进行编码 */public static String encodeBytes(byte[] source, int off, int len) {return encodeBytes(source, off, len, true);}/** * 实际进行编码的方法 */public static String encodeBytes(byte[] source, int off, int len, boolean breakLines) {int len43 = len * 4 / 3 , d = 0, e = 0 , len2 = len - 2, lineLength = 0;byte[] outBuff = new byte[len43 + ((len % 3) > 0 ? 4 : 0) + (breakLines ? (len43 / MAX_LINE_LENGTH) : 0)];for(;d < len2; d += 3, e += 4) {encode3to4(source, d+off, 3, outBuff, e);lineLength += 4;if(breakLines && lineLength == MAX_LINE_LENGTH) {outBuff[e + 4] = NEW_LINE;e++;lineLength = 0;}}if(d < len) {encode3to4(source, d+off, len-d, outBuff, e);e += 4;}return new String(outBuff, 0, e);}/** * 对String进行编码 */public static String encodeString(String s) {return encodeString(s, true);}/** * 对String进行编码 */public static String encodeString(String s, boolean breakLines) {return encodeBytes(s.getBytes(), breakLines);}/** * 按照Base64编码串行化对象Object */public static String encodeobject(Serializable sobj) {return encodeObject(sobj, true);}/** * 实际串行化对象Object */public static String encodeObject(Serializable sobj, boolean breakLines) {ByteArrayOutputStream baos = null;OutputStream b64os = null;ObjectOutputStream oos = null;try {baos = new ByteArrayOutputStream();b64os = new Base64.OutStream(baos, ENCODE, breakLines);oos = new ObjectOutputStream(b64os);oos.writeObject(sobj);} catch(IOException e) {e.printStackTrace();return null;} finally {try {oos.close();} catch (IOException e1) {e1.printStackTrace();}try {b64os.close();} catch (IOException e1) {e1.printStackTrace();}try {baos.close();} catch (IOException e1) {e1.printStackTrace();}}return new String(baos.toByteArray());}/** * 读取文件中的数据 */public static byte[] readFile(String file, boolean encode) {return readFile(new File(file), encode);}/** * 根据encode参数,读取文件中的数据 */public static byte[] readFile(File file, boolean encode) {byte[] data = new byte[1024];//文件中的字符数不能超过1024byte[] returnValue = null;int nextIndex = 0;int b = -1;Base64.InStream bis = null;try {bis = new Base64.InStream(new BufferedInputStream(new FileInputStream(file)), encode);while((b = bis.read()) >= 0) {if(nextIndex > data.length) {//重新设定数组长度byte[] temp = new byte[data.length << 1];System.arraycopy(data, 0, temp, 0, data.length);//截取数组data = temp;}data[nextIndex++] = (byte)b;}returnValue = new byte[nextIndex];System.arraycopy(data, 0, returnValue, 0, nextIndex);} catch (IOException e) {returnValue = null;} finally {try {if(bis != null)bis.close();} catch (IOException e) {}}return returnValue;}/** * 将字节数组写入文件 */public static boolean writeFile(byte[] data, String file, boolean encode) {return writeFile(data, 0, data.length, new File(file), encode);}/** * 将字节数组写入文件 */public static boolean writeFile(byte[] data, File file, boolean encode) {return writeFile(data, 0, data.length, file, encode);}/** * 根据encode参数,将字节数组写入文件 */public static boolean writeFile(byte[] data, int offset, int length, File file, boolean encode) {Base64.OutStream bos = null;boolean success = false;try {bos = new Base64.OutStream(new BufferedOutputStream(new FileOutputStream(file)), encode);bos.write(data, offset, length);success = true;} catch (IOException e) {success = false;} finally {try {bos.close();} catch (IOException e) {}}return success;}/** * 对文件数据进行编码,返回编码后的字符串,抛异常则返回null */public static String encodeFromFile(String rawfile) {byte[] ebytes = readFile(rawfile, ENCODE);return ebytes == null ? null : new String(ebytes);}/** * 对文件数据进行解码,返回解码后的字符串,抛异常则返回null */public static byte[] decodeFromFile(String encfile) {return readFile(encfile, DECODE);}/** * 将编码后的数据写入文件 */public static boolean encodeToFile(byte[] rawdata, String file) {return writeFile(rawdata, file, ENCODE);}/** * 将解码后的数据写入文件 */public static boolean decodeToFile(byte[] encdata, String file) {return writeFile(encdata, file, DECODE);}/** * 对fourBytes数组进行解码,并返回解码后的数组 */private static byte[] decode4to3(byte[] fourBytes) {byte[] outBuff1 = new byte[3];int count = decode4to3(fourBytes, 0, outBuff1, 0);byte[] outBuff2 = new byte[count];for(int i=0; i<count; i++) outBuff2[i] = outBuff1[i];return outBuff2;}/** * 对fourBytes数组进行解码,并返回解码后的数组 */private static int decode4to3(byte[] source, int srcOffset, byte[] destination, int destOffset) {if(source[srcOffset + 2] == EQUALS_SIGN) {int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18) | ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12);destination[destOffset] = (byte)(outBuff >>> 16);return 1;} else if(source[srcOffset + 3] == EQUALS_SIGN) {int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18) | ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12) | ((DECODABET[source[srcOffset + 2]] & 0xFF) << 6);destination[destOffset] = (byte)(outBuff >>> 16);destination[destOffset + 1] = (byte)(outBuff >>> 8);return 2;} else {int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18) | ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12) | ((DECODABET[source[srcOffset + 2]] & 0xFF) << 6) | ((DECODABET[source[srcOffset + 3]] & 0xFF));destination[destOffset] = (byte)(outBuff >> 16);destination[destOffset + 1] = (byte)(outBuff >> 8);destination[destOffset + 2] = (byte)(outBuff);return 3;}}/** * 对String进行解码,并返回解码后的数组 */public static byte[] decode(String s) {byte[] bytes = s.getBytes();return decode(bytes, 0, bytes.length);}/** * 对String进行解码,并返回String */public static String decodeToString(String s) {return new String(decode(s));}/** * 对Base64规范的数据进行解码,并且反串行化得到一个java对象 */public static Object decodeToObject(String encodeedObject) {byte[] objBytes = decode(encodeedObject);ByteArrayInputStream bais = null;ObjectInputStream ois = null;try {bais = new ByteArrayInputStream(objBytes);ois = new ObjectInputStream(bais);return ois.readObject();} catch (IOException e) {e.printStackTrace();return null;} catch (ClassNotFoundException e) {e.printStackTrace();return null;} finally {try {bais.close();} catch (IOException e) {}try {ois.close();} catch (IOException e) {}}}/** * 对Base64规范的数据进行解码 */public static byte[] decode(byte[] source, int off, int len) {int len34 = len * 3 / 4, outBuffPosn = 0, b4Posn = 0, i = 0;byte[] outBuff = new byte[len34];byte[] b4 = new byte[4];byte sbiCrop = 0;byte sbiDecode = 0;for(i=0; i<len; i++) {sbiCrop = (byte)(source[i] & 0x7f);//只需要低位的7个bitsbiDecode = DECODABET[sbiCrop];if(sbiDecode >= WHITE_SPACE_ENC) {//空格if(sbiDecode >= EQUALS_SIGN_ENC) {//==b4[b4Posn++] = sbiCrop;if(b4Posn > 3) {outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn);b4Posn = 0;//如果没有"=="就跳出循环if(sbiCrop == EQUALS_SIGN) break;}}} else {return null;}}byte[] out = new byte[outBuffPosn];System.arraycopy(outBuff, 0, out, 0, outBuffPosn);return out;}}