2017-05-18 20:42:57 +08:00
|
|
|
|
package org.csource.common;
|
|
|
|
|
|
|
|
|
|
import java.io.IOException;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Freeware from:
|
|
|
|
|
* Roedy Green
|
|
|
|
|
* Canadian Mind Products
|
|
|
|
|
* #327 - 964 Heywood Avenue
|
|
|
|
|
* Victoria, BC Canada V8V 2Y5
|
|
|
|
|
* tel:(250) 361-9093
|
|
|
|
|
* mailto:roedy@mindprod.com
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Encode arbitrary binary into printable ASCII using BASE64 encoding.
|
|
|
|
|
* very loosely based on the Base64 Reader by
|
|
|
|
|
* Dr. Mark Thornton
|
|
|
|
|
* Optrak Distribution Software Ltd.
|
|
|
|
|
* http://www.optrak.co.uk
|
|
|
|
|
* and Kevin Kelley's http://www.ruralnet.net/~kelley/java/Base64.java
|
2017-05-19 09:56:24 +08:00
|
|
|
|
* <p>
|
2017-05-18 20:42:57 +08:00
|
|
|
|
* Base64 is a way of encoding 8-bit characters using only ASCII printable
|
|
|
|
|
* characters similar to UUENCODE. UUENCODE includes a filename where BASE64 does not.
|
|
|
|
|
* The spec is described in RFC 2045. Base64 is a scheme where
|
|
|
|
|
* 3 bytes are concatenated, then split to form 4 groups of 6-bits each; and
|
|
|
|
|
* each 6-bits gets translated to an encoded printable ASCII character, via a
|
|
|
|
|
* table lookup. An encoded string is therefore longer than the original by
|
|
|
|
|
* about 1/3. The "=" character is used to pad the end. Base64 is used,
|
|
|
|
|
* among other things, to encode the user:password string in an
|
|
|
|
|
* Authorization: header for HTTP. Don't confuse Base64 with
|
|
|
|
|
* x-www-form-urlencoded which is handled by
|
|
|
|
|
* Java.net.URLEncoder.encode/decode
|
|
|
|
|
* If you don't like this code, there is another implementation at http://www.ruffboy.com/download.htm
|
|
|
|
|
* Sun has an undocumented method called sun.misc.Base64Encoder.encode.
|
|
|
|
|
* You could use hex, simpler to code, but not as compact.
|
2017-05-19 09:56:24 +08:00
|
|
|
|
* <p>
|
2017-05-18 20:42:57 +08:00
|
|
|
|
* If you wanted to encode a giant file, you could do it in large chunks that
|
|
|
|
|
* are even multiples of 3 bytes, except for the last chunk, and append the outputs.
|
2017-05-19 09:56:24 +08:00
|
|
|
|
* <p>
|
2017-05-18 20:42:57 +08:00
|
|
|
|
* To encode a string, rather than binary data java.net.URLEncoder may be better. See
|
|
|
|
|
* printable characters in the Java glossary for a discussion of the differences.
|
2017-05-19 09:56:24 +08:00
|
|
|
|
* <p>
|
2017-05-18 20:42:57 +08:00
|
|
|
|
* version 1.4 2002 February 15 -- correct bugs with uneven line lengths,
|
2017-05-19 09:56:24 +08:00
|
|
|
|
* allow you to configure line separator.
|
|
|
|
|
* now need Base64 object and instance methods.
|
|
|
|
|
* new mailing address.
|
2017-05-18 20:42:57 +08:00
|
|
|
|
* version 1.3 2000 September 12 -- fix problems with estimating output length in encode
|
|
|
|
|
* version 1.2 2000 September 09 -- now handles decode as well.
|
|
|
|
|
* version 1.1 1999 December 04 -- more symmetrical encoding algorithm.
|
2017-05-19 09:56:24 +08:00
|
|
|
|
* more accurate StringBuffer allocation size.
|
2017-05-18 20:42:57 +08:00
|
|
|
|
* version 1.0 1999 December 03 -- posted in comp.lang.java.programmer.
|
|
|
|
|
* Futures Streams or files.
|
|
|
|
|
*/
|
|
|
|
|
|
2017-05-19 09:56:24 +08:00
|
|
|
|
public class Base64 {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Marker value for chars we just ignore, e.g. \n \r high ascii
|
|
|
|
|
*/
|
|
|
|
|
static final int IGNORE = -1;
|
|
|
|
|
/**
|
|
|
|
|
* Marker for = trailing pad
|
|
|
|
|
*/
|
|
|
|
|
static final int PAD = -2;
|
|
|
|
|
/**
|
|
|
|
|
* used to disable test driver
|
|
|
|
|
*/
|
|
|
|
|
private static final boolean debug = true;
|
|
|
|
|
/**
|
|
|
|
|
* how we separate lines, e.g. \n, \r\n, \r etc.
|
|
|
|
|
*/
|
|
|
|
|
private String lineSeparator = System.getProperty("line.separator");
|
|
|
|
|
/**
|
|
|
|
|
* max chars per line, excluding lineSeparator. A multiple of 4.
|
|
|
|
|
*/
|
|
|
|
|
private int lineLength = 72;
|
|
|
|
|
private char[] valueToChar = new char[64];
|
|
|
|
|
/**
|
|
|
|
|
* binary value encoded by a given letter of the alphabet 0..63
|
|
|
|
|
*/
|
|
|
|
|
private int[] charToValue = new int[256];
|
|
|
|
|
private int[] charToPad = new int[4];
|
|
|
|
|
|
|
|
|
|
/* constructor */
|
|
|
|
|
public Base64() {
|
|
|
|
|
this.init('+', '/', '=');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* constructor */
|
|
|
|
|
public Base64(char chPlus, char chSplash, char chPad, int lineLength) {
|
|
|
|
|
this.init(chPlus, chSplash, chPad);
|
|
|
|
|
this.lineLength = lineLength;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Base64(int lineLength) {
|
|
|
|
|
this.lineLength = lineLength;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* debug display array
|
|
|
|
|
*/
|
|
|
|
|
public static void show(byte[] b) {
|
|
|
|
|
int count = 0;
|
|
|
|
|
int rows = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < b.length; i++) {
|
|
|
|
|
if (count == 8) {
|
|
|
|
|
System.out.print(" ");
|
|
|
|
|
} else if (count == 16) {
|
|
|
|
|
System.out.println("");
|
|
|
|
|
count = 0;
|
|
|
|
|
continue;
|
2017-05-18 20:42:57 +08:00
|
|
|
|
}
|
2017-05-19 09:56:24 +08:00
|
|
|
|
System.out.print(Integer.toHexString(b[i] & 0xFF).toUpperCase() + " ");
|
|
|
|
|
count++;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
System.out.println();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* debug display array
|
|
|
|
|
*/
|
|
|
|
|
public static void display(byte[] b) {
|
|
|
|
|
for (int i = 0; i < b.length; i++) {
|
|
|
|
|
System.out.print((char) b[i]);
|
|
|
|
|
}
|
|
|
|
|
System.out.println();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* test driver
|
|
|
|
|
*/
|
|
|
|
|
public static void main(String[] args) {
|
|
|
|
|
test();
|
|
|
|
|
System.exit(1);
|
|
|
|
|
|
|
|
|
|
if (debug) {
|
|
|
|
|
try {
|
|
|
|
|
Base64 b64 = new Base64();
|
|
|
|
|
String str = "agfrtu¿¦etʲ1234¼Ù´óerty¿Õ234·¢¿¦2344ʲµÄ";
|
|
|
|
|
String str64 = "";
|
|
|
|
|
|
|
|
|
|
//encode
|
|
|
|
|
str64 = b64.encode(str.getBytes());
|
|
|
|
|
System.out.println(str64);
|
|
|
|
|
|
|
|
|
|
//decode
|
|
|
|
|
byte[] theBytes = b64.decode(str64);
|
|
|
|
|
show(theBytes);
|
|
|
|
|
String rst = new String(theBytes);
|
|
|
|
|
System.out.println(rst);
|
|
|
|
|
System.out.println(str);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
e.printStackTrace();
|
2017-05-18 20:42:57 +08:00
|
|
|
|
}
|
2017-05-19 09:56:24 +08:00
|
|
|
|
//getBytes(String charsetName);
|
2017-05-18 20:42:57 +08:00
|
|
|
|
/*
|
|
|
|
|
byte[] a = { (byte)0xfc, (byte)0x0f, (byte)0xc0};
|
|
|
|
|
byte[] b = { (byte)0x03, (byte)0xf0, (byte)0x3f};
|
|
|
|
|
byte[] c = { (byte)0x00, (byte)0x00, (byte)0x00};
|
|
|
|
|
byte[] d = { (byte)0xff, (byte)0xff, (byte)0xff};
|
|
|
|
|
byte[] e = { (byte)0xfc, (byte)0x0f, (byte)0xc0, (byte)1};
|
|
|
|
|
byte[] f = { (byte)0xfc, (byte)0x0f, (byte)0xc0, (byte)1, (byte)2};
|
|
|
|
|
byte[] g = { (byte)0xfc, (byte)0x0f, (byte)0xc0, (byte)1, (byte)2, (byte)3};
|
|
|
|
|
byte[] h = "AAAAAAAAAAB".getBytes();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
show(a);
|
|
|
|
|
show(b);
|
|
|
|
|
show(c);
|
|
|
|
|
show(d);
|
|
|
|
|
show(e);
|
|
|
|
|
show(f);
|
|
|
|
|
show(g);
|
|
|
|
|
show(h);
|
|
|
|
|
Base64 b64 = new Base64();
|
|
|
|
|
show(b64.decode(b64.encode(a)));
|
|
|
|
|
show(b64.decode(b64.encode(b)));
|
|
|
|
|
show(b64.decode(b64.encode(c)));
|
|
|
|
|
show(b64.decode(b64.encode(d)));
|
|
|
|
|
show(b64.decode(b64.encode(e)));
|
|
|
|
|
show(b64.decode(b64.encode(f)));
|
|
|
|
|
show(b64.decode(b64.encode(g)));
|
|
|
|
|
show(b64.decode(b64.encode(h)));
|
|
|
|
|
b64.setLineLength(8);
|
|
|
|
|
show((b64.encode(h)).getBytes());
|
|
|
|
|
*/
|
2017-05-19 09:56:24 +08:00
|
|
|
|
}
|
|
|
|
|
}// end main
|
|
|
|
|
|
|
|
|
|
public static void test() {
|
|
|
|
|
try {
|
|
|
|
|
Base64 b64 = new Base64();
|
|
|
|
|
|
|
|
|
|
//encode
|
|
|
|
|
//str64 = b64.encode(str.getBytes());
|
|
|
|
|
//System.out.println(str64);
|
|
|
|
|
|
|
|
|
|
String str64 = "CwUEFYoAAAADjQMC7ELJiY6w05267ELJiY6w05267ELJiY6w05267ELJiY6w05267ELJiY6w05267ELJiY6w05267ELJiY6w05267ELJiY6w05267ELJiY6w05267ELJiY6w05267ELJiY6w05267ELJiY6w05267ELJiY6w05267ELJiY6w05267EI=";
|
|
|
|
|
//decode
|
|
|
|
|
byte[] theBytes = b64.decode(str64);
|
|
|
|
|
show(theBytes);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* initialise defaultValueToChar and defaultCharToValue tables */
|
|
|
|
|
private void init(char chPlus, char chSplash, char chPad) {
|
|
|
|
|
int index = 0;
|
|
|
|
|
// build translate this.valueToChar table only once.
|
|
|
|
|
// 0..25 -> 'A'..'Z'
|
|
|
|
|
for (int i = 'A'; i <= 'Z'; i++) {
|
|
|
|
|
this.valueToChar[index++] = (char) i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 26..51 -> 'a'..'z'
|
|
|
|
|
for (int i = 'a'; i <= 'z'; i++) {
|
|
|
|
|
this.valueToChar[index++] = (char) i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 52..61 -> '0'..'9'
|
|
|
|
|
for (int i = '0'; i <= '9'; i++) {
|
|
|
|
|
this.valueToChar[index++] = (char) i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.valueToChar[index++] = chPlus;
|
|
|
|
|
this.valueToChar[index++] = chSplash;
|
|
|
|
|
|
|
|
|
|
// build translate defaultCharToValue table only once.
|
|
|
|
|
for (int i = 0; i < 256; i++) {
|
|
|
|
|
this.charToValue[i] = IGNORE; // default is to ignore
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 64; i++) {
|
|
|
|
|
this.charToValue[this.valueToChar[i]] = i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.charToValue[chPad] = PAD;
|
|
|
|
|
java.util.Arrays.fill(this.charToPad, chPad);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Encode an arbitrary array of bytes as Base64 printable ASCII.
|
|
|
|
|
* It will be broken into lines of 72 chars each. The last line is not
|
|
|
|
|
* terminated with a line separator.
|
|
|
|
|
* The output will always have an even multiple of data characters,
|
|
|
|
|
* exclusive of \n. It is padded out with =.
|
|
|
|
|
*/
|
|
|
|
|
public String encode(byte[] b) throws IOException {
|
|
|
|
|
// Each group or partial group of 3 bytes becomes four chars
|
|
|
|
|
// covered quotient
|
|
|
|
|
int outputLength = ((b.length + 2) / 3) * 4;
|
|
|
|
|
|
|
|
|
|
// account for trailing newlines, on all but the very last line
|
|
|
|
|
if (lineLength != 0) {
|
|
|
|
|
int lines = (outputLength + lineLength - 1) / lineLength - 1;
|
|
|
|
|
if (lines > 0) {
|
|
|
|
|
outputLength += lines * lineSeparator.length();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// must be local for recursion to work.
|
|
|
|
|
StringBuffer sb = new StringBuffer(outputLength);
|
|
|
|
|
|
|
|
|
|
// must be local for recursion to work.
|
|
|
|
|
int linePos = 0;
|
|
|
|
|
|
|
|
|
|
// first deal with even multiples of 3 bytes.
|
|
|
|
|
int len = (b.length / 3) * 3;
|
|
|
|
|
int leftover = b.length - len;
|
|
|
|
|
for (int i = 0; i < len; i += 3) {
|
|
|
|
|
// Start a new line if next 4 chars won't fit on the current line
|
|
|
|
|
// We can't encapsulete the following code since the variable need to
|
|
|
|
|
// be local to this incarnation of encode.
|
|
|
|
|
linePos += 4;
|
|
|
|
|
if (linePos > lineLength) {
|
|
|
|
|
if (lineLength != 0) {
|
|
|
|
|
sb.append(lineSeparator);
|
|
|
|
|
}
|
|
|
|
|
linePos = 4;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// get next three bytes in unsigned form lined up,
|
|
|
|
|
// in big-endian order
|
|
|
|
|
int combined = b[i + 0] & 0xff;
|
|
|
|
|
combined <<= 8;
|
|
|
|
|
combined |= b[i + 1] & 0xff;
|
|
|
|
|
combined <<= 8;
|
|
|
|
|
combined |= b[i + 2] & 0xff;
|
|
|
|
|
|
|
|
|
|
// break those 24 bits into a 4 groups of 6 bits,
|
|
|
|
|
// working LSB to MSB.
|
|
|
|
|
int c3 = combined & 0x3f;
|
|
|
|
|
combined >>>= 6;
|
|
|
|
|
int c2 = combined & 0x3f;
|
|
|
|
|
combined >>>= 6;
|
|
|
|
|
int c1 = combined & 0x3f;
|
|
|
|
|
combined >>>= 6;
|
|
|
|
|
int c0 = combined & 0x3f;
|
|
|
|
|
|
|
|
|
|
// Translate into the equivalent alpha character
|
|
|
|
|
// emitting them in big-endian order.
|
|
|
|
|
sb.append(valueToChar[c0]);
|
|
|
|
|
sb.append(valueToChar[c1]);
|
|
|
|
|
sb.append(valueToChar[c2]);
|
|
|
|
|
sb.append(valueToChar[c3]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// deal with leftover bytes
|
|
|
|
|
switch (leftover) {
|
|
|
|
|
case 0:
|
|
|
|
|
default:
|
|
|
|
|
// nothing to do
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
|
// One leftover byte generates xx==
|
|
|
|
|
// Start a new line if next 4 chars won't fit on the current line
|
|
|
|
|
linePos += 4;
|
|
|
|
|
if (linePos > lineLength) {
|
|
|
|
|
|
|
|
|
|
if (lineLength != 0) {
|
|
|
|
|
sb.append(lineSeparator);
|
|
|
|
|
}
|
|
|
|
|
linePos = 4;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Handle this recursively with a faked complete triple.
|
|
|
|
|
// Throw away last two chars and replace with ==
|
|
|
|
|
sb.append(encode(new byte[]{b[len], 0, 0}
|
|
|
|
|
).substring(0, 2));
|
|
|
|
|
sb.append("==");
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
|
// Two leftover bytes generates xxx=
|
|
|
|
|
// Start a new line if next 4 chars won't fit on the current line
|
|
|
|
|
linePos += 4;
|
|
|
|
|
if (linePos > lineLength) {
|
|
|
|
|
if (lineLength != 0) {
|
|
|
|
|
sb.append(lineSeparator);
|
|
|
|
|
}
|
|
|
|
|
linePos = 4;
|
|
|
|
|
}
|
|
|
|
|
// Handle this recursively with a faked complete triple.
|
|
|
|
|
// Throw away last char and replace with =
|
|
|
|
|
sb.append(encode(new byte[]{b[len], b[len + 1], 0}
|
|
|
|
|
).substring(0, 3));
|
|
|
|
|
sb.append("=");
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
} // end switch;
|
|
|
|
|
|
|
|
|
|
if (outputLength != sb.length()) {
|
|
|
|
|
System.out.println("oops: minor program flaw: output length mis-estimated");
|
|
|
|
|
System.out.println("estimate:" + outputLength);
|
|
|
|
|
System.out.println("actual:" + sb.length());
|
|
|
|
|
}
|
|
|
|
|
return sb.toString();
|
|
|
|
|
}// end encode
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* decode a well-formed complete Base64 string back into an array of bytes.
|
|
|
|
|
* It must have an even multiple of 4 data characters (not counting \n),
|
|
|
|
|
* padded out with = as needed.
|
|
|
|
|
*/
|
|
|
|
|
public byte[] decodeAuto(String s) {
|
|
|
|
|
int nRemain = s.length() % 4;
|
|
|
|
|
if (nRemain == 0) {
|
|
|
|
|
return this.decode(s);
|
|
|
|
|
} else {
|
|
|
|
|
return this.decode(s + new String(this.charToPad, 0, 4 - nRemain));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* decode a well-formed complete Base64 string back into an array of bytes.
|
|
|
|
|
* It must have an even multiple of 4 data characters (not counting \n),
|
|
|
|
|
* padded out with = as needed.
|
|
|
|
|
*/
|
|
|
|
|
public byte[] decode(String s) {
|
|
|
|
|
|
|
|
|
|
// estimate worst case size of output array, no embedded newlines.
|
|
|
|
|
byte[] b = new byte[(s.length() / 4) * 3];
|
|
|
|
|
|
|
|
|
|
// tracks where we are in a cycle of 4 input chars.
|
|
|
|
|
int cycle = 0;
|
|
|
|
|
|
|
|
|
|
// where we combine 4 groups of 6 bits and take apart as 3 groups of 8.
|
|
|
|
|
int combined = 0;
|
|
|
|
|
|
|
|
|
|
// how many bytes we have prepared.
|
|
|
|
|
int j = 0;
|
|
|
|
|
// will be an even multiple of 4 chars, plus some embedded \n
|
|
|
|
|
int len = s.length();
|
|
|
|
|
int dummies = 0;
|
|
|
|
|
for (int i = 0; i < len; i++) {
|
|
|
|
|
|
|
|
|
|
int c = s.charAt(i);
|
|
|
|
|
int value = (c <= 255) ? charToValue[c] : IGNORE;
|
|
|
|
|
// there are two magic values PAD (=) and IGNORE.
|
|
|
|
|
switch (value) {
|
|
|
|
|
case IGNORE:
|
|
|
|
|
// e.g. \n, just ignore it.
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PAD:
|
|
|
|
|
value = 0;
|
|
|
|
|
dummies++;
|
|
|
|
|
// fallthrough
|
|
|
|
|
default:
|
|
|
|
|
/* regular value character */
|
|
|
|
|
switch (cycle) {
|
|
|
|
|
case 0:
|
|
|
|
|
combined = value;
|
|
|
|
|
cycle = 1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
|
combined <<= 6;
|
|
|
|
|
combined |= value;
|
|
|
|
|
cycle = 2;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
|
combined <<= 6;
|
|
|
|
|
combined |= value;
|
|
|
|
|
cycle = 3;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
|
combined <<= 6;
|
|
|
|
|
combined |= value;
|
|
|
|
|
// we have just completed a cycle of 4 chars.
|
|
|
|
|
// the four 6-bit values are in combined in big-endian order
|
|
|
|
|
// peel them off 8 bits at a time working lsb to msb
|
|
|
|
|
// to get our original 3 8-bit bytes back
|
|
|
|
|
|
|
|
|
|
b[j + 2] = (byte) combined;
|
|
|
|
|
combined >>>= 8;
|
|
|
|
|
b[j + 1] = (byte) combined;
|
|
|
|
|
combined >>>= 8;
|
|
|
|
|
b[j] = (byte) combined;
|
|
|
|
|
j += 3;
|
|
|
|
|
cycle = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
} // end for
|
|
|
|
|
if (cycle != 0) {
|
|
|
|
|
throw new ArrayIndexOutOfBoundsException("Input to decode not an even multiple of 4 characters; pad with =.");
|
|
|
|
|
}
|
|
|
|
|
j -= dummies;
|
|
|
|
|
if (b.length != j) {
|
|
|
|
|
byte[] b2 = new byte[j];
|
|
|
|
|
System.arraycopy(b, 0, b2, 0, j);
|
|
|
|
|
b = b2;
|
|
|
|
|
}
|
|
|
|
|
return b;
|
|
|
|
|
|
|
|
|
|
}// end decode
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* determines how long the lines are that are generated by encode.
|
|
|
|
|
* Ignored by decode.
|
|
|
|
|
*
|
|
|
|
|
* @param length 0 means no newlines inserted. Must be a multiple of 4.
|
|
|
|
|
*/
|
|
|
|
|
public void setLineLength(int length) {
|
|
|
|
|
this.lineLength = (length / 4) * 4;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* How lines are separated.
|
|
|
|
|
* Ignored by decode.
|
|
|
|
|
*
|
|
|
|
|
* @param lineSeparator may be "" but not null.
|
|
|
|
|
* Usually contains only a combination of chars \n and \r.
|
|
|
|
|
* Could be any chars not in set A-Z a-z 0-9 + /.
|
|
|
|
|
*/
|
|
|
|
|
public void setLineSeparator(String lineSeparator) {
|
|
|
|
|
this.lineSeparator = lineSeparator;
|
|
|
|
|
}
|
2017-05-18 20:42:57 +08:00
|
|
|
|
} // end Base64
|
|
|
|
|
|