The previous article learned the principle of Base64 encoding, the following is the implementation of Java:
Public final class Base64 {
private static final byte PAD = (byte) ' = ';
private static final int baselength = 255;
private static final int lookuplength = 64;
private static final int sign = -128;//8 bit full 1
private static byte[] Base64alphabet = new Byte[baselength];
private static byte[] Lookupbase64alphabet = new Byte[lookuplength];
Populating the lookup and character arrays
static {
for (int i = 0; i < baselength; i++) {
Base64alphabet[i] = (byte)-1;
}
for (int i = ' Z '; I >= ' A '; i--) {
Base64alphabet[i] = (byte) (i-' A ');
}
for (int i = ' z '; I >= ' a '; i--) {
Base64alphabet[i] = (byte) (i-' a ' + 26);
}
for (int i = ' 9 '; I >= ' 0 '; i--) {
Base64alphabet[i] = (byte) (i-' 0 ' + 52);
}
base64alphabet[' + '] = 62;
base64alphabet['/'] = 63;
for (int i = 0; I <=; i++) {
Lookupbase64alphabet[i] = (byte) (' A ' + i);
}
for (int i = n, j = 0; I <=; i++, J + +) {
Lookupbase64alphabet[i] = (byte) (' a ' + j);
}
for (int i = k, j = 0; I <=; i++, J + +) {
Lookupbase64alphabet[i] = (byte) (' 0 ' + j);
}
LOOKUPBASE64ALPHABET[62] = (byte) ' + ';
LOOKUPBASE64ALPHABET[63] = (byte) '/';
}
/**
* Encodes binary data using the Base64 algorithm, optionally chunking the output into character blocks.
*
* @param binarydata Array containing binary data to encode.
* @return base64-encoded data.
*/
public static byte[] EncodeBase64 (byte[] binarydata) {
int lengthdatabits = Binarydata.length * 8;
int fewerthan24bits = lengthdatabits% 24;
int numbertriplets = LENGTHDATABITS/24;
byte encodeddata[] = null;
int encodeddatalength = 0;
if (fewerthan24bits! = 0) {
Data not divisible by
Encodeddatalength = (numbertriplets + 1) * 4;
} else {
or 8 bit
Encodeddatalength = numbertriplets * 4;
}
Encodeddata = new Byte[encodeddatalength];
byte k = 0, L = 0, B1 = 0, b2 = 0, B3 = 0;
int encodedindex = 0;
int dataindex = 0;
int i = 0;
Log.debug ("Number of triplets =" + numbertriplets);
for (i = 0; i < numbertriplets; i++) {
Dataindex = i * 3;
B1 = Binarydata[dataindex];
b2 = Binarydata[dataindex + 1];
B3 = Binarydata[dataindex + 2];
Log.debug ("b1=" + B1 + ", b2=" + b2 + ", b3=" + B3);
L = (byte) (B2 & 0x0f);//First 4 bits
k = (Byte) (B1 & 0x03);//First 2 bits
byte Val1 = ((B1 & sign) = = 0)? (byte) (B1 >> 2): (Byte) ((B1) >> 2 ^ 0xc0);//>> priority higher than ^, take first 6 bits
byte Val2 = ((b2 & sign) = = 0)? (byte) (B2 >> 4): (Byte) ((B2) >> 4 ^ 0xf0);//Take the first 4 bits
byte Val3 = ((b3 & sign) = = 0)? (byte) (B3 >> 6): (Byte) ((B3) >> 6 ^ 0xfc);//Take the first 2 bits
Encodeddata[encodedindex] = Lookupbase64alphabet[val1];
Log.debug ("val2 =" + Val2);
Log.debug ("K4 =" + (k<<4));
Log.debug ("Vak =" + (Val2 | (k<<4)) );
Encodeddata[encodedindex + 1] = Lookupbase64alphabet[val2 | (k << 4)];
Encodeddata[encodedindex + 2] = lookupbase64alphabet[(l << 2) | val3];
Encodeddata[encodedindex + 3] = lookupbase64alphabet[b3 & 0x3f];//take last 6 bits
Encodedindex + = 4;
}
Form integral number of 6-bit groups
Dataindex = i * 3;
if (fewerthan24bits = = 8) {
B1 = Binarydata[dataindex];
k = (Byte) (B1 & 0x03);
Log.debug ("b1=" + B1);
Log.debug ("b1<<2 =" + (b1>>2));
byte Val1 = ((B1 & sign) = = 0)? (byte) (B1 >> 2): (Byte) ((B1) >> 2 ^ 0xc0);
Encodeddata[encodedindex] = Lookupbase64alphabet[val1];
Encodeddata[encodedindex + 1] = Lookupbase64alphabet[k << 4];
Encodeddata[encodedindex + 2] = PAD;
Encodeddata[encodedindex + 3] = PAD;
} else if (fewerthan24bits = = 16) {
B1 = Binarydata[dataindex];
b2 = Binarydata[dataindex + 1];
L = (byte) (B2 & 0x0f);
k = (Byte) (B1 & 0x03);
byte Val1 = ((B1 & sign) = = 0)? (byte) (B1 >> 2): (Byte) ((B1) >> 2 ^ 0xc0);
byte Val2 = ((b2 & sign) = = 0)? (byte) (B2 >> 4): (Byte) ((B2) >> 4 ^ 0xf0);
Encodeddata[encodedindex] = Lookupbase64alphabet[val1];
Encodeddata[encodedindex + 1] = Lookupbase64alphabet[val2 | (k << 4)];
Encodeddata[encodedindex + 2] = Lookupbase64alphabet[l << 2];
Encodeddata[encodedindex + 3] = PAD;
}
return encodeddata;
}
/**
* Decodes Base64 data into octects
*
* @param base64data Byte array containing Base64 data
* @return Array containing decoded data.
*/
public static byte[] DecodeBase64 (byte[] base64data) {
Handle the edge case, so we don ' t has to worry about it later
if (Base64data.length = = 0) {
return new byte[0];
}
int numberquadruple = BASE64DATA.LENGTH/4;
byte decodeddata[] = null;
BYTE B1 = 0, b2 = 0, B3 = 0, b4 = 0, Marker0 = 0, marker1 = 0;
Throw away anything not in Base64data
int encodedindex = 0;
int dataindex = 0;
{
This sizes the output array PROPERLY-RLW
int lastdata = Base64data.length;
Ignore the ' = ' padding
while (base64data[lastdata-1] = = PAD) {
if (--lastdata = = 0) {
return new byte[0];
}
}
Decodeddata = new Byte[lastdata-numberquadruple];
}
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) {
Both PAD e.g. 3c[pad][pad]
Decodeddata[encodedindex] = (byte) (B1 << 2 | b2 >> 4);
} 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));
}
Encodedindex + = 3;
}
return decodeddata;
}
}
Java implementation of BASE64