package com.doumee.core.utils;
|
|
/**
|
* Base64文件字符串处理工具类
|
*
|
* @ClassName Base64Util
|
* @Description TODO
|
* @author jfli@woyitech.com
|
* @date 2016年5月27日 上午11:46:34
|
*/
|
public final class Base64Util {
|
|
/**
|
* NO_OPTIONS=0
|
*/
|
public static final int NO_OPTIONS = 0;
|
/**
|
* ENCODE = 1
|
*/
|
public static final int ENCODE = 1;
|
|
/**
|
* DECODE = 0
|
*/
|
public static final int DECODE = 0;
|
|
/**
|
* GZIP = 2
|
*/
|
public static final int GZIP = 2;
|
/**
|
* DONT_BREAK_LINES = 8
|
*/
|
public static final int DONT_BREAK_LINES = 8;
|
/**
|
* MAX_LINE_LENGTH = 76
|
*/
|
private static final int MAX_LINE_LENGTH = 76;
|
|
/**
|
* EQUALS_SIGN(=)
|
*/
|
private static final byte EQUALS_SIGN = (byte) '=';
|
|
/**
|
* NEW_LINE(enter)
|
*/
|
private static final byte NEW_LINE = (byte) '\n';
|
|
/**
|
* PREFERRED_ENCODING(UTF-8)
|
*/
|
private static final String PREFERRED_ENCODING = "UTF-8";
|
|
/**
|
* ALPHABET
|
*/
|
private static final byte[] ALPHABET;
|
|
/**
|
* _NATIVE_ALPHABET
|
*/
|
private static final byte[] PRI_NATIVE_ALPHABET = new byte[] {
|
(byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D',
|
(byte) 'E', (byte) 'F', (byte) 'G', (byte) 'H', (byte) 'I',
|
(byte) 'J', (byte) 'K', (byte) 'L', (byte) 'M',
|
(byte) 'N', (byte) 'O', (byte) 'P', (byte) 'Q', (byte) 'R',
|
(byte) 'S', (byte) 'T', (byte) 'U', (byte) 'V',
|
(byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z', (byte) 'a',
|
(byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e',
|
(byte) 'f', (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j',
|
(byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n',
|
(byte) 'o', (byte) 'p', (byte) 'q', (byte) 'r', (byte) 's',
|
(byte) 't', (byte) 'u', (byte) 'v', (byte) 'w',
|
(byte) 'x', (byte) 'y', (byte) 'z', (byte) '0', (byte) '1',
|
(byte) '2', (byte) '3', (byte) '4', (byte) '5',
|
(byte) '6', (byte) '7', (byte) '8', (byte) '9', (byte) '+', (byte) '/' };
|
|
static {
|
byte[] priBytes = null;
|
try {
|
priBytes =
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
|
.getBytes(PREFERRED_ENCODING);
|
} catch (java.io.UnsupportedEncodingException use) {
|
priBytes = PRI_NATIVE_ALPHABET; // Fall back to native encoding
|
} // end catch
|
ALPHABET = priBytes;
|
} // end static
|
|
/**
|
* DECODABET
|
*/
|
private static final byte[] DECODABET = { -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal// 0// -// 8
|
-5, -5, // Whitespace: Tab and Linefeed
|
-9, -9, // Decimal 11 - 12
|
-5, // Whitespace: Carriage Return
|
-9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - // 26
|
-9, -9, -9, -9, -9, // Decimal 27 - 31
|
-5, // Whitespace: Space
|
-9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 42
|
62, // Plus sign at decimal 43
|
-9, -9, -9, // Decimal 44 - 46
|
63, // Slash at decimal 47
|
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine
|
-9, -9, -9, // Decimal 58 - 60
|
-1, // Equals sign at decimal 61
|
-9, -9, -9, // Decimal 62 - 64
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // Letters 'A' through // 'N'
|
14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // Letters 'O'// through 'Z'
|
-9, -9, -9, -9, -9, -9, // Decimal 91 - 96
|
26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // Letters 'a'// through 'm'
|
39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // Letters 'n'// through 'z'
|
-9, -9, -9, -9 // Decimal 123 - 126
|
|
};
|
|
// I think I end up not using the BAD_ENCODING indicator.
|
// private final static byte BAD_ENCODING = -9; // Indicates error in
|
// encoding
|
/**
|
* WHITE_SPACE_ENC = -5
|
*/
|
private static final byte WHITE_SPACE_ENC = -5; // Indicates white space in
|
// encoding
|
/**
|
* EQUALS_SIGN_ENC = -1
|
*/
|
private static final byte EQUALS_SIGN_ENC = -1; // Indicates equals sign in // encoding
|
|
/**
|
* 默认构造器
|
* @Title Base64Util
|
* @Description TODO
|
*/
|
private Base64Util() {
|
}
|
|
/**
|
* 加密byte数组
|
*
|
* @param b4
|
* @param threeBytes
|
* @param numSigBytes
|
* @return byte数组
|
*/
|
private static byte[] encode3to4(byte[] b4, byte[] threeBytes, int numSigBytes) {
|
encode3to4(threeBytes, 0, numSigBytes, b4, 0);
|
return b4;
|
} // end encode3to4
|
|
/**
|
* 加密byte数组
|
*
|
* @param source
|
* @param srcOffset
|
* @param numSigBytes
|
* @param destination
|
* @param destOffset
|
* @return byte数组
|
*/
|
private static byte[] encode3to4(byte[] source, int srcOffset,
|
int numSigBytes, byte[] destination,
|
int destOffset) {
|
// 1 2 3
|
// 01234567890123456789012345678901 Bit position
|
// --------000000001111111122222222 Array position from threeBytes
|
// --------| || || || | Six bit groups to index ALPHABET
|
// >>18 >>12 >> 6 >> 0 Right shift necessary
|
// 0x3f 0x3f 0x3f Additional AND
|
|
// Create buffer with zero-padding if there are only one or two
|
// significant bytes passed in the array.
|
// We have to shift left 24 in order to flush out the 1's that appear
|
// when Java treats a value as negative that is cast from a byte to an
|
// int.
|
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;
|
} // end switch
|
} // end encode3to4
|
|
/**
|
* 序列化对象转化字符串
|
*
|
* @param serializableObject
|
* @return 字符串
|
*/
|
public static String encodeObject(java.io.Serializable serializableObject) {
|
return encodeObject(serializableObject, NO_OPTIONS);
|
} // end encodeObject
|
|
/**
|
* 序列化对象转化字符串
|
*
|
* @param serializableObject
|
* @param options
|
* @return 字符串
|
*/
|
public static String encodeObject(java.io.Serializable serializableObject, int options) {
|
// Streams
|
java.io.ByteArrayOutputStream baos = null;
|
java.io.OutputStream b64os = null;
|
java.io.ObjectOutputStream oos = null;
|
java.util.zip.GZIPOutputStream gzos = null;
|
|
// Isolate options
|
int gzip = (options & GZIP);
|
int dontBreakLines = (options & DONT_BREAK_LINES);
|
|
try {
|
// ObjectOutputStream -> (GZIP) -> Base64 -> ByteArrayOutputStream
|
baos = new java.io.ByteArrayOutputStream();
|
b64os = new OutputStream(baos, ENCODE | dontBreakLines);
|
|
// GZip?
|
if (gzip == GZIP) {
|
gzos = new java.util.zip.GZIPOutputStream(b64os);
|
oos = new java.io.ObjectOutputStream(gzos);
|
// end if: gzip
|
} else {
|
oos = new java.io.ObjectOutputStream(b64os);
|
}
|
oos.writeObject(serializableObject);
|
// end try
|
} catch (java.io.IOException e) {
|
e.printStackTrace();
|
return null;
|
// end catch
|
} finally {
|
try {
|
oos.close();
|
} catch (Exception e) {
|
}
|
try {
|
gzos.close();
|
} catch (Exception e) {
|
}
|
try {
|
b64os.close();
|
} catch (Exception e) {
|
}
|
try {
|
baos.close();
|
} catch (Exception e) {
|
}
|
} // end finally
|
|
// Return value according to relevant encoding.
|
try {
|
return new String(baos.toByteArray(), PREFERRED_ENCODING);
|
// end try
|
} catch (java.io.UnsupportedEncodingException uue) {
|
return new String(baos.toByteArray());
|
} // end catch
|
|
} // end encode
|
|
/**
|
* byte数组转化字符串
|
*
|
* @param source
|
* @return 字符串
|
*/
|
public static String encodeBytes(byte[] source) {
|
return encodeBytes(source, 0, source.length, NO_OPTIONS);
|
} // end encodeBytes
|
|
/**
|
* byte数组转化字符串
|
*
|
* @param source
|
* @param options
|
* @return 字符串
|
*/
|
public static String encodeBytes(byte[] source, int options) {
|
return encodeBytes(source, 0, source.length, options);
|
} // end encodeBytes
|
|
/**
|
* byte数组转化字符串
|
*
|
* @param source
|
* @param off
|
* @param len
|
* @return 字符串
|
*/
|
public static String encodeBytes(byte[] source, int off, int len) {
|
return encodeBytes(source, off, len, NO_OPTIONS);
|
} // end encodeBytes
|
|
/**
|
* byte数组转化字符串
|
*
|
* @param source
|
* @param off
|
* @param len
|
* @param options
|
* @return 字符串
|
*/
|
public static String encodeBytes(byte[] source, int off, int len, int options) {
|
// Isolate options
|
int dontBreakLines = (options & DONT_BREAK_LINES);
|
int gzip = (options & GZIP);
|
|
// Compress?
|
if (gzip == GZIP) {
|
java.io.ByteArrayOutputStream baos = null;
|
java.util.zip.GZIPOutputStream gzos = null;
|
OutputStream b64os = null;
|
|
try {
|
// GZip -> Base64 -> ByteArray
|
baos = new java.io.ByteArrayOutputStream();
|
b64os = new OutputStream(baos, ENCODE | dontBreakLines);
|
gzos = new java.util.zip.GZIPOutputStream(b64os);
|
|
gzos.write(source, off, len);
|
gzos.close();
|
// end try
|
} catch (java.io.IOException e) {
|
e.printStackTrace();
|
return null;
|
// end catch
|
} finally {
|
try {
|
gzos.close();
|
} catch (Exception e) {
|
}
|
try {
|
b64os.close();
|
} catch (Exception e) {
|
}
|
try {
|
baos.close();
|
} catch (Exception e) {
|
}
|
} // end finally
|
|
// Return value according to relevant encoding.
|
try {
|
return new String(baos.toByteArray(), PREFERRED_ENCODING);
|
// end try
|
} catch (java.io.UnsupportedEncodingException uue) {
|
return new String(baos.toByteArray());
|
} // end catch
|
// end if: compress
|
} else {
|
// Else, don't compress. Better not to use streams at all then.
|
// Convert option to boolean in way that code likes it.
|
boolean breakLines = dontBreakLines == 0;
|
|
int len43 = len * 4 / 3;
|
byte[] outBuff = new byte[(len43) // Main 4:3
|
+ ((len % 3) > 0 ? 4 : 0) // Account for padding
|
+ (breakLines ? (len43 / MAX_LINE_LENGTH) : 0)]; // New // lines
|
int d = 0;
|
int e = 0;
|
int len2 = len - 2;
|
int lineLength = 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;
|
} // end if: end of line
|
} // en dfor: each piece of array
|
|
if (d < len) {
|
encode3to4(source, d + off, len - d, outBuff, e);
|
e += 4;
|
} // end if: some padding needed
|
|
// Return value according to relevant encoding.
|
try {
|
return new String(outBuff, 0, e, PREFERRED_ENCODING);
|
// end try
|
} catch (java.io.UnsupportedEncodingException uue) {
|
return new String(outBuff, 0, e);
|
} // end catch
|
|
} // end else: don't compress
|
|
} // end encodeBytes
|
|
/**
|
* 表示看不懂,求补充
|
*
|
* @param source
|
* @param srcOffset
|
* @param destination
|
* @param destOffset
|
* @return int
|
*/
|
private static int decode4to3(byte[] source, int srcOffset,
|
byte[] destination, int destOffset) {
|
// Example: Dk==
|
if (source[srcOffset + 2] == EQUALS_SIGN) {
|
// Two ways to do the same thing. Don't know which way I like best.
|
// int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6
|
// )
|
// | ( ( DECODABET[ source[ srcOffset + 1] ] << 24 ) >>> 12 );
|
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) {// Example: DkL=
|
// Two ways to do the same thing. Don't know which way I like best.
|
// int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6
|
// )
|
// | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 )
|
// | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 );
|
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 {// Example: DkLE
|
try {
|
// Two ways to do the same thing. Don't know which way I like
|
// best.
|
// int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 )
|
// >>> 6 )
|
// | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 )
|
// | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 )
|
// | ( ( DECODABET[ source[ srcOffset + 3 ] ] << 24 ) >>> 24 );
|
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;
|
} catch (Exception e) {
|
// System.out.println(""+source[srcOffset]+ ": " + ( DECODABET[
|
// source[ srcOffset ] ] ) );
|
// System.out.println(""+source[srcOffset+1]+ ": " + (
|
// DECODABET[ source[ srcOffset + 1 ] ] ) );
|
// System.out.println(""+source[srcOffset+2]+ ": " + (
|
// DECODABET[ source[ srcOffset + 2 ] ] ) );
|
// System.out.println(""+source[srcOffset+3]+ ": " + (
|
// DECODABET[ source[ srcOffset + 3 ] ] ) );
|
return -1;
|
} // e nd catch
|
}
|
} // end decodeToBytes
|
|
/**
|
* 加密byte数据
|
*
|
* @param source
|
* 原byte数组
|
* @param off
|
* 开始位置
|
* @param len
|
* 长度
|
* @return byte数组
|
*/
|
public static byte[] decode(byte[] source, int off, int len) {
|
int len34 = len * 3 / 4;
|
byte[] outBuff = new byte[len34]; // Upper limit on size of output
|
int outBuffPosn = 0;
|
|
byte[] b4 = new byte[4];
|
int b4Posn = 0;
|
int i = 0;
|
byte sbiCrop = 0;
|
byte sbiDecode = 0;
|
for (i = off; i < off + len; i++) {
|
sbiCrop = (byte) (source[i] & 0x7f); // Only the low seven bits
|
sbiDecode = DECODABET[sbiCrop];
|
|
if (sbiDecode >= WHITE_SPACE_ENC){ // White space, Equals sign or
|
// better
|
|
if (sbiDecode >= EQUALS_SIGN_ENC) {
|
b4[b4Posn++] = sbiCrop;
|
if (b4Posn > 3) {
|
outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn);
|
b4Posn = 0;
|
|
// If that was the equals sign, break out of 'for' loop
|
if (sbiCrop == EQUALS_SIGN){
|
break;
|
}
|
} // end if: quartet built
|
|
} // end if: equals sign or better
|
// end if: white space, equals sign or better
|
} else {
|
System.err.println("Bad Base64 input character at "
|
+ i + ": " + source[i] + "(decimal)");
|
return null;
|
} // end else:
|
} // each input character
|
|
byte[] out = new byte[outBuffPosn];
|
System.arraycopy(outBuff, 0, out, 0, outBuffPosn);
|
return out;
|
} // end decode
|
|
/**
|
* 将字符串转化为byte数组
|
*
|
* @param s
|
* @return byte数组
|
*/
|
public static byte[] decode(String s) {
|
byte[] bytes;
|
try {
|
bytes = s.getBytes(PREFERRED_ENCODING);
|
// end try
|
} catch (java.io.UnsupportedEncodingException uee) {
|
bytes = s.getBytes();
|
} // end catch
|
// </change>
|
|
// Decode
|
bytes = decode(bytes, 0, bytes.length);
|
|
// Check to see if it's gzip-compressed
|
// GZIP Magic Two-Byte Number: 0x8b1f (35615)
|
if (bytes != null && bytes.length >= 4) {
|
|
int head = ((int) bytes[0] & 0xff) | ((bytes[1] << 8) & 0xff00);
|
if (java.util.zip.GZIPInputStream.GZIP_MAGIC == head) {
|
java.io.ByteArrayInputStream bais = null;
|
java.util.zip.GZIPInputStream gzis = null;
|
java.io.ByteArrayOutputStream baos = null;
|
byte[] buffer = new byte[2048];
|
int length = 0;
|
|
try {
|
baos = new java.io.ByteArrayOutputStream();
|
bais = new java.io.ByteArrayInputStream(bytes);
|
gzis = new java.util.zip.GZIPInputStream(bais);
|
|
while ((length = gzis.read(buffer)) >= 0) {
|
baos.write(buffer, 0, length);
|
} // end while: reading input
|
|
// No error? Get new bytes.
|
bytes = baos.toByteArray();
|
// end try
|
} catch (java.io.IOException e) {
|
// Just return originally-decoded bytes
|
// end catch
|
} finally {
|
try {
|
baos.close();
|
} catch (Exception e) {
|
}
|
try {
|
gzis.close();
|
} catch (Exception e) {
|
}
|
try {
|
bais.close();
|
} catch (Exception e) {
|
}
|
} // end finally
|
|
} // end if: gzipped
|
} // end if: bytes.length >= 2
|
|
return bytes;
|
} // end decode
|
|
/**
|
* 将字符串转化为Object对象
|
*
|
* @param encodedObject
|
* @return Object
|
*/
|
public static Object decodeToObject(String encodedObject) {
|
// Decode and gunzip if necessary
|
byte[] objBytes = decode(encodedObject);
|
|
java.io.ByteArrayInputStream bais = null;
|
java.io.ObjectInputStream ois = null;
|
Object obj = null;
|
|
try {
|
bais = new java.io.ByteArrayInputStream(objBytes);
|
ois = new java.io.ObjectInputStream(bais);
|
|
obj = ois.readObject();
|
// end try
|
} catch (java.io.IOException e) {
|
e.printStackTrace();
|
obj = null;
|
} catch (ClassNotFoundException e) {
|
e.printStackTrace();
|
obj = null;
|
} finally {
|
try {
|
bais.close();
|
} catch (Exception e) {
|
}
|
try {
|
ois.close();
|
} catch (Exception e) {
|
}
|
} // end finally
|
|
return obj;
|
} // end decodeObject
|
|
/**
|
* 将byte数组转换成文件
|
*
|
* @param dataToEncode
|
* 需要转换的byte数组
|
* @param filename
|
* 文件名,带后缀
|
* @return 是否转换成功
|
*/
|
public static boolean encodeToFile(byte[] dataToEncode, String filename) {
|
boolean success = false;
|
OutputStream bos = null;
|
try {
|
bos = new OutputStream(new java.io.FileOutputStream(filename),
|
Base64Util.ENCODE);
|
bos.write(dataToEncode);
|
success = true;
|
// end try
|
} catch (java.io.IOException e) {
|
|
success = false;
|
// end catch: IOException
|
} finally {
|
try {
|
bos.close();
|
} catch (Exception e) {
|
}
|
} // end finally
|
|
return success;
|
} // end encodeToFile
|
|
/**
|
* 将加密字符串转换成文件
|
*
|
* @param dataToDecode
|
* 加密字符串
|
* @param filename
|
* 文件名,带后缀
|
* @return 是否转换成功
|
*/
|
public static boolean decodeToFile(String dataToDecode, String filename) {
|
boolean success = false;
|
OutputStream bos = null;
|
try {
|
bos = new OutputStream(new java.io.FileOutputStream(filename),
|
Base64Util.DECODE);
|
bos.write(dataToDecode.getBytes(PREFERRED_ENCODING));
|
success = true;
|
// end try
|
} catch (java.io.IOException e) {
|
success = false;
|
// end catch: IOException
|
} finally {
|
try {
|
bos.close();
|
} catch (Exception e) {
|
}
|
} // end finally
|
|
return success;
|
} // end decodeToFile
|
|
/**
|
* 将文件加密成byte数组
|
*
|
* @param filename
|
* 文件名,带后缀
|
* @return byte数组
|
*/
|
public static byte[] decodeFromFile(String filename) {
|
byte[] decodedData = null;
|
InputStream bis = null;
|
try {
|
// Set up some useful variables
|
java.io.File file = new java.io.File(filename);
|
byte[] buffer = null;
|
int length = 0;
|
int numBytes = 0;
|
|
// Check for size of file
|
if (file.length() > Integer.MAX_VALUE) {
|
System.err.println("File is too big for this convenience method ("
|
+ file.length() + " bytes).");
|
return null;
|
} // end if: file too big for int index
|
buffer = new byte[(int) file.length()];
|
|
// Open a stream
|
bis = new InputStream(
|
new java.io.BufferedInputStream(new java.io.FileInputStream(file)),
|
Base64Util.DECODE);
|
|
// Read until done
|
while ((numBytes = bis.read(buffer, length, 4096)) >= 0){
|
length += numBytes;
|
}
|
// Save in a variable to return
|
decodedData = new byte[length];
|
System.arraycopy(buffer, 0, decodedData, 0, length);
|
// end try
|
} catch (java.io.IOException e) {
|
System.err.println("Error decoding from file " + filename);
|
// end catch: IOException
|
} finally {
|
try {
|
bis.close();
|
} catch (Exception e) {
|
}
|
} // end finally
|
|
return decodedData;
|
} // end decodeFromFile
|
|
/**
|
* 将文件转换成字符串
|
*
|
* @param filename
|
* @return 文件转换后的字符串
|
*/
|
public static String encodeFromFile(String filename) {
|
String encodedData = null;
|
InputStream bis = null;
|
try {
|
// Set up some useful variables
|
java.io.File file = new java.io.File(filename);
|
byte[] buffer = new byte[(int) (file.length() * 1.4)];
|
int length = 0;
|
int numBytes = 0;
|
|
// Open a stream
|
bis = new InputStream(new java.io.BufferedInputStream(
|
new java.io.FileInputStream(file)),
|
Base64Util.ENCODE);
|
|
// Read until done
|
while ((numBytes = bis.read(buffer, length, 4096)) >= 0){
|
length += numBytes;
|
}
|
|
// Save in a variable to return
|
encodedData = new String(buffer, 0, length, Base64Util.PREFERRED_ENCODING);
|
// end try
|
} catch (java.io.IOException e) {
|
System.err.println("Error encoding from file " + filename);
|
// end catch: IOException
|
} finally {
|
try {
|
bis.close();
|
} catch (Exception e) {
|
}
|
} // end finally
|
|
return encodedData;
|
} // end encodeFromFile
|
|
/**
|
* 内部类InputStream
|
* @ClassName InputStream
|
* @Description TODO
|
* @author jfli@woyitech.com
|
* @date 2016年5月27日 下午12:27:42
|
*/
|
public static class InputStream extends java.io.FilterInputStream {
|
/**
|
* Encoding or decoding
|
*/
|
private boolean encode; // Encoding or decoding
|
/**
|
* Current position in the buffer
|
*/
|
private int position; //
|
/**
|
* Small buffer holding converted data
|
*/
|
private byte[] buffer; //
|
/**
|
* Length of buffer (3 or 4)
|
*/
|
private int bufferLength; //
|
/**
|
* Number of meaningful bytes in the buffer
|
*/
|
private int numSigBytes; //
|
/**
|
* lineLength
|
*/
|
private int lineLength;
|
/**
|
* Break lines at less than 80 characters
|
*/
|
private boolean breakLines; //
|
|
/**
|
* 构造函数
|
* @Title InputStream
|
* @Description TODO
|
* @param in
|
*/
|
public InputStream(java.io.InputStream in) {
|
this(in, DECODE);
|
} // end constructor
|
|
/**
|
* 构造函数
|
* @Title InputStream
|
* @Description TODO
|
* @param in
|
* @param options
|
*/
|
public InputStream(java.io.InputStream in, int options) {
|
super(in);
|
this.breakLines = (options & DONT_BREAK_LINES) != DONT_BREAK_LINES;
|
this.encode = (options & ENCODE) == ENCODE;
|
this.bufferLength = encode ? 4 : 3;
|
this.buffer = new byte[bufferLength];
|
this.position = -1;
|
this.lineLength = 0;
|
} // end constructor
|
|
/**
|
* read
|
* @return int
|
*/
|
public int read() throws java.io.IOException {
|
// Do we need to get data?
|
if (position < 0) {
|
if (encode) {
|
byte[] b3 = new byte[3];
|
int numBinaryBytes = 0;
|
for (int i = 0; i < 3; i++) {
|
try {
|
int b = in.read();
|
|
// If end of stream, b is -1.
|
if (b >= 0) {
|
b3[i] = (byte) b;
|
numBinaryBytes++;
|
} // end if: not end of stream
|
// end try: read
|
} catch (java.io.IOException e) {
|
// Only a problem if we got no data at all.
|
if (i == 0){
|
throw e;
|
}
|
|
} // end catch
|
} // end for: each needed input byte
|
|
if (numBinaryBytes > 0) {
|
encode3to4(b3, 0, numBinaryBytes, buffer, 0);
|
position = 0;
|
numSigBytes = 4;
|
// end if: got data
|
} else {
|
return -1;
|
} // end else
|
// end if: encoding
|
}else {// Else decoding
|
byte[] b4 = new byte[4];
|
int i = 0;
|
for (i = 0; i < 4; i++) {
|
// Read four "meaningful" bytes:
|
int b = 0;
|
do {
|
b = in.read();
|
} while (b >= 0 && DECODABET[b & 0x7f] <= WHITE_SPACE_ENC);
|
|
if (b < 0){
|
break; // Reads a -1 if end of stream
|
}
|
|
b4[i] = (byte) b;
|
} // end for: each needed input byte
|
|
if (i == 4) {
|
numSigBytes = decode4to3(b4, 0, buffer, 0);
|
position = 0;
|
// end if: got four characters
|
} else if (i == 0) {
|
return -1;
|
// end else if: also padded correctly
|
} else {
|
// Must have broken out from above.
|
throw new java.io.IOException("Improperly padded Base64 input.");
|
} // end
|
|
} // end else: decode
|
} // end else: get data
|
|
// Got data?
|
if (position >= 0) {
|
// End of relevant data?
|
if (position >= numSigBytes){
|
return -1;
|
}
|
|
if (encode && breakLines && lineLength >= MAX_LINE_LENGTH) {
|
lineLength = 0;
|
return '\n';
|
// end if
|
} else {
|
lineLength++; // This isn't important when decoding
|
// but throwing an extra "if" seems
|
// just as wasteful.
|
|
int b = buffer[position++];
|
|
if (position >= bufferLength){
|
position = -1;
|
}
|
return b & 0xFF; // This is how you "cast" a byte that's
|
// intended to be unsigned.
|
} // end else
|
// end if: position >= 0
|
} else {// Else error
|
// When JDK1.4 is more accepted, use an assertion here.
|
throw new java.io.IOException("Error in Base64 code reading stream.");
|
} // end else
|
} // end read
|
|
/**
|
* read
|
* @return int
|
*/
|
public int read(byte[] dest, int off, int len) throws java.io.IOException {
|
int i;
|
int b;
|
for (i = 0; i < len; i++) {
|
b = read();
|
|
// if( b < 0 && i == 0 )
|
// return -1;
|
|
if (b >= 0){
|
dest[off + i] = (byte) b;
|
}else if (i == 0){
|
return -1;
|
}else{
|
break; // Out of 'for' loop
|
}
|
} // end for: each byte read
|
return i;
|
} // end read
|
|
} // end inner class InputStream
|
/**
|
* 内部类OutputStream
|
* @ClassName OutputStream
|
* @Description TODO
|
* @author jfli@woyitech.com
|
* @date 2016年5月27日 下午12:32:55
|
*/
|
public static class OutputStream extends java.io.FilterOutputStream {
|
/**
|
* Encoding or decoding
|
*/
|
private boolean encode;
|
/**
|
* Current position in the buffer
|
*/
|
private int position;
|
/**
|
* Small buffer holding converted data
|
*/
|
private byte[] buffer;
|
/**
|
* Length of buffer (3 or 4)
|
*/
|
private int bufferLength;
|
/**
|
* lineLength
|
*/
|
private int lineLength;
|
/**
|
* Number of meaningful bytes in the buffer
|
*/
|
private boolean breakLines;
|
/**
|
* Scratch used in a few places
|
*/
|
private byte[] b4; //
|
/**
|
* suspendEncoding
|
*/
|
private boolean suspendEncoding;
|
/**
|
* 构造函数
|
* @Title OutputStream
|
* @Description TODO
|
* @param out
|
*/
|
public OutputStream(java.io.OutputStream out) {
|
this(out, ENCODE);
|
} // end constructor
|
/**
|
* 构造函数
|
* @Title OutputStream
|
* @Description TODO
|
* @param out
|
*/
|
public OutputStream(java.io.OutputStream out, int options) {
|
super(out);
|
this.breakLines = (options & DONT_BREAK_LINES) != DONT_BREAK_LINES;
|
this.encode = (options & ENCODE) == ENCODE;
|
this.bufferLength = encode ? 3 : 4;
|
this.buffer = new byte[bufferLength];
|
this.position = 0;
|
this.lineLength = 0;
|
this.suspendEncoding = false;
|
this.b4 = new byte[4];
|
} // end constructor
|
|
/**
|
* write
|
*/
|
public void write(int theByte) throws java.io.IOException {
|
// Encoding suspended?
|
if (suspendEncoding) {
|
super.out.write(theByte);
|
return;
|
} // end if: supsended
|
|
// Encode?
|
if (encode) {
|
buffer[position++] = (byte) theByte;
|
if (position >= bufferLength) {// Enough to encode.
|
|
out.write(encode3to4(b4, buffer, bufferLength));
|
|
lineLength += 4;
|
if (breakLines && lineLength >= MAX_LINE_LENGTH) {
|
out.write(NEW_LINE);
|
lineLength = 0;
|
} // end if: end of line
|
|
position = 0;
|
} // end if: enough to output
|
// end if: encoding
|
} else {// Else, Decoding
|
// Meaningful Base64 character?
|
if (DECODABET[theByte & 0x7f] > WHITE_SPACE_ENC) {
|
buffer[position++] = (byte) theByte;
|
if (position >= bufferLength) {// Enough to output.
|
|
int len = Base64Util.decode4to3(buffer, 0, b4, 0);
|
out.write(b4, 0, len);
|
// out.write( Base64.decode4to3( buffer ) );
|
position = 0;
|
} // end if: enough to output
|
// end if: meaningful base64 character
|
} else if (DECODABET[theByte & 0x7f] != WHITE_SPACE_ENC) {
|
throw new java.io.IOException("Invalid character in Base64 data.");
|
} // end else: not white space either
|
} // end else: decoding
|
} // end write
|
|
/**
|
* write
|
*/
|
public void write(byte[] theBytes, int off, int len) throws java.io.IOException {
|
// Encoding suspended?
|
if (suspendEncoding) {
|
super.out.write(theBytes, off, len);
|
return;
|
} // end if: supsended
|
|
for (int i = 0; i < len; i++) {
|
write(theBytes[off + i]);
|
} // end for: each byte written
|
|
} // end write
|
|
/**
|
* flushBase64
|
* @Title flushBase64
|
* @Description TODO
|
* @author jfli@woyitech.com
|
* @throws java.io.IOException
|
* @return
|
*/
|
public void flushBase64() throws java.io.IOException {
|
if (position > 0) {
|
if (encode) {
|
out.write(encode3to4(b4, buffer, position));
|
position = 0;
|
} else {// end if: encoding
|
throw new java.io.IOException("Base64 input not properly padded.");
|
} // end else: decoding
|
} // end if: buffer partially full
|
|
} // end flush
|
/**
|
* close
|
*/
|
public void close() throws java.io.IOException {
|
// 1. Ensure that pending characters are written
|
flushBase64();
|
|
// 2. Actually close the stream
|
// Base class both flushes and closes.
|
super.close();
|
|
buffer = null;
|
out = null;
|
} // end close
|
|
/**
|
* suspendEncoding = true
|
* @Title suspendEncoding
|
* @Description TODO
|
* @author jfli@woyitech.com
|
* @throws java.io.IOException
|
* @return
|
*/
|
public void suspendEncoding() throws java.io.IOException {
|
flushBase64();
|
this.suspendEncoding = true;
|
} // end suspendEncoding
|
|
/**
|
* suspendEncoding = false
|
* @Title resumeEncoding
|
* @Description TODO
|
* @author jfli@woyitech.com
|
* @return
|
*/
|
public void resumeEncoding() {
|
this.suspendEncoding = false;
|
} // end resumeEncoding
|
|
} // end inner class OutputStream
|
|
// public static void main(String[] args) {
|
//
|
// String filePath = "F:\\test\\跨境电商事业部通讯录(合肥研发中心)-20140722.doc";
|
//
|
// String str = Base64Util.encodeFromFile(filePath);
|
//
|
// Base64Util.decodeToFile(str, "F:\\123.doc");
|
// }
|
}
|