Base64编码

来源:互联网 发布:stc12c5a16s2 编程 编辑:程序博客网 时间:2024/06/01 07:38
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;}}

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 新疆办理暂住证有案底不办给怎么办 我的驾驶证吊销了车年审怎么办 好几个超速分不够扣了怎么办 刚拿c1驾照扣6分怎么办 别人开我车扣12分怎么办 办健康证大便拉不出来怎么办 欠信用卡钱被网上通缉抓到后怎么办 上海房子卖了户口没地方迁怎么办 没有户口本在北京身份证丢了怎么办 武汉科目四考试居住证过期了怎么办 农行卡密码输错3次怎么办 驾照罚款缴纳了网上没消怎么办 外地驾驶证分数扣12分了怎么办 有生产日期的赠品在超市过期怎么办 6年免检车辆逾期未年检怎么办 行驶证检验有效期过期2年怎么办 骑摩托车忘带驾驶证和行驶证怎么办 驾驶证逾期未审验怎么办有什么后果 车祸至人腿部骨折沒钱偿还的怎么办 我有c4驾驶证想办c3怎么办 驾驶证和行驶证被交警扣了怎么办 行驶证被交警弄丢了怎么办 没带行驶证让警察发现怎么办 首尔转机换票换乘怎么办过境签证 驾驶证约考帐号与登密码丢失怎么办 考驾照的时候预约密码忘了怎么办 考驾照的预约密码忘了怎么办 摩托车不能挂档不能摘挡了怎么办 身份证丢失了派出所不给挂失怎么办 快递员在中午还送货夏天怎么办啊 驾照一个记分周期扣满12分怎么办 佛山南海车管所怎么办替人消分流程 福州快处中心几流程要怎么办 被对方追尾了对方只有交强险怎么办 摩托车行驶证年检过期一年半怎么办 户口迁到杭州了身份证掉了怎么办 户口已迁至外面要补办结婚证怎么办 汽车年检时间过了1个月怎么办 户口在老家在北京工作怎么办招工 报考驾照时手机号留错了怎么办 合肥驾照换证体检没过怎么办