I. Overview
What is 1.base64:
Base64 is one of the most common coding methods for transmitting 8Bit byte code on the network, and you can view the rfc2045~rfc2049, which has a MIME detail specification. The BASE64 encoding can be used to pass longer identity information in an HTTP environment. For example, in the Java Persistence System hibernate, Base64 is used to encode a long unique identifier (typically a 128-bit uuid) as a string, as a parameter in an HTTP form and an HTTP GET URL. In other applications, it is often necessary to encode binary data into a form appropriate to the URL, including hidden form fields. At this point, the use of BASE64 encoding is not only shorter, but also has the readability, that is, the encoded data will not be directly visible to the naked eye
2. Introduction:
The standard Base64 is not suitable for transmission directly to the URL. Because the URL encoder will change the "/" and "+" characters in the standard Base64 to form "%xx", these "%" numbers will need to be converted when they are stored in the database, because the ANSI SQL has "%" Number is used as a wildcard character.
To solve this problem, you can use an improved BASE64 encoding for URLs, it does not populate the ' = ' number at the end, and changes the "+" and "/" in the standard Base64 to "*" and "-", thus eliminating the conversion to be made when the URL is encoded and stored in the database. It avoids the increase of the length of encoded information in this process, and unifies the format of object identifiers such as databases, forms, and so on.
There is also an improved BASE64 variant for regular expressions, which changes "+" and "/" to "!" and "-", because "+", "*", and "[" and "]" previously used in IRCU may have special meanings in regular expressions.
In addition, there are variants that change "+/" to "_-" or ". _" (used as the identifier name in the programming language) or ".-" (for NmToken in XML) or even "_:" (for name in XML).
BASE64 requires converting every three 8Bit bytes to four 6Bit bytes (3*8 = 4*6 = 24), and then adding 6Bit two-bit high 0 to form four 8Bit bytes, that is, the converted string is theoretically going to be 1/3 longer than the original.
3. Rules:
About the rules for this encoding:
① 3 characters into 4 characters.
②. Alphanumeric a newline character for every 76 characters ...
③. The final terminator also to be dealt with.
Wouldn't it be too abstract to say so? Don't worry, let's take a look at an example:
Before conversion: Aaaaaabb ccccdddd EEFFFFFF
After conversion: 00AAAAAA 00BBCCCC 00ddddee 00ffffff
It should be clear, right? The three bytes above are original, the following four bytes are converted Base64 encodings, and the first two digits are 0.
After the conversion, we use a code table to get the string we want (that is, the final Base64 encoding)
Two, Java implementation code example:
Public final class Base64 {static private final int baselength = 255;
Static private final int lookuplength = 64;
Static private final int twentyfourbitgroup = 24;
Static private final int eightbit = 8;
Static private final int sixteenbit = 16;
Static private final int sixbit = 6;
Static private final int fourbyte = 4;
Static private final int SIGN =-128;
Static private final char PAD = ' = ';
Static Private Final Boolean fdebug = false;
Static final private byte[] Base64alphabet = new Byte[baselength];
Static final private char[] Lookupbase64alphabet = new Char[lookuplength];
static {for (int i = 0; i < baselength i++) {Base64alphabet[i] =-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] = (char) (' A ' + i);
for (int i =, j = 0; I <= i++, j + +) Lookupbase64alphabet[i] = (char) (' a ' + j);
for (int i =, j = 0; I <= i++, j + +) Lookupbase64alphabet[i] = (char) (' 0 ' + j);
LOOKUPBASE64ALPHABET[62] = (char) ' + ';
LOOKUPBASE64ALPHABET[63] = (char) '/'; Protected static Boolean iswhitespace (char octect) {return (Octect = = 0x20 | | octect = 0XD | | octect = 0xa | | octe
CT = = 0x9);
} protected static Boolean Ispad (char octect) {return (Octect = = PAD);
} protected static Boolean Isdata (char octect) {return (Base64alphabet[octect]!=-1);
} protected static Boolean isBase64 (char octect) {return (Iswhitespace (octect) | | ispad (octect) | | isdata (octect)); }/** * encodes hex octects into Base64 * * @param binarydata * Array containing binarydata * @return encoded
Base64 Array */public static String encode (byte[] binarydata) {if (BinaryData = null) return null;
int lengthdatabits = Binarydata.length * eightbit;
if (lengthdatabits = = 0) {return "";
int fewerthan24bits = lengthdatabits% Twentyfourbitgroup;
int numbertriplets = Lengthdatabits/twentyfourbitgroup; int numberquartet = fewerthan24bits!= 0?
Numbertriplets + 1:numbertriplets;
int numberlines = (numberQuartet-1)/19 + 1;
char encodeddata[] = null;
Encodeddata = new Char[numberquartet * 4 + numberlines];
byte k = 0, L = 0, B1 = 0, b2 = 0, B3 = 0;
int encodedindex = 0;
int dataindex = 0;
int i = 0;
if (fdebug) {System.out.println ("number of triplets =" + numbertriplets); for (int line = 0; line < numberLines-1 line++) {for (int quartet = 0; quartet < quartet++) {B1 = b
Inarydata[dataindex++];
b2 = binarydata[dataindex++];
B3 = binarydata[dataindex++];
if (fdebug) {System.out.println ("b1=" + B1 + ", b2=" + b2 + ", b3=" + B3);
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); byte Val3 = ((B3 & SIGN) = = 0)? (byte)
(B3 >> 6): (Byte) ((B3) >> 6 ^ 0xfc);
if (fdebug) {System.out.println ("val2 =" + Val2);
System.out.println ("K4 =" + (k << 4)); System.out.println ("Vak =" + (Val2 |
(k << 4)));
} encodeddata[encodedindex++] = Lookupbase64alphabet[val1]; encodeddata[encodedindex++] = Lookupbase64alphabet[val2 |
(k << 4)];
encodeddata[encodedindex++] = lookupbase64alphabet[(l << 2) | val3];
encodeddata[encodedindex++] = lookupbase64alphabet[b3 & 0x3f];
i++;
} encodeddata[encodedindex++] = 0xa;
for (; i < numbertriplets; i++) {b1 = binarydata[dataindex++];
b2 = binarydata[dataindex++];
B3 = binarydata[dataindex++]; if (fdebug) {System.out.println ("b1=" + B1 +), b2= "+ b2 +", b3= "+ B3);
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); byte Val3 = ((B3 & SIGN) = = 0)? (byte)
(B3 >> 6): (Byte) ((B3) >> 6 ^ 0xfc);
if (fdebug) {System.out.println ("val2 =" + Val2);
System.out.println ("K4 =" + (k << 4)); System.out.println ("Vak =" + (Val2 |
(k << 4)));
} encodeddata[encodedindex++] = Lookupbase64alphabet[val1]; encodeddata[encodedindex++] = Lookupbase64alphabet[val2 |
(k << 4)];
encodeddata[encodedindex++] = lookupbase64alphabet[(l << 2) | val3];
encodeddata[encodedindex++] = lookupbase64alphabet[b3 & 0x3f];
}//form integral number of 6-bit groups if (fewerthan24bits = = eightbit) {B1 = Binarydata[dataindex];
k = (Byte) (B1 & 0x03); if (fdebug) {System.ouT.println ("b1=" + B1);
System.out.println ("b1<<2 =" + (B1 >> 2)); byte Val1 = ((B1 & SIGN) = = 0)? (byte)
(B1 >> 2): (Byte) ((B1) >> 2 ^ 0xc0);
encodeddata[encodedindex++] = Lookupbase64alphabet[val1];
encodeddata[encodedindex++] = lookupbase64alphabet[k << 4];
encodeddata[encodedindex++] = PAD;
encodeddata[encodedindex++] = PAD;
else if (fewerthan24bits = = sixteenbit) {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++] = Lookupbase64alphabet[val2 |
(k << 4)];
encodeddata[encodedindex++] = lookupbase64alphabet[l << 2];
encodeddata[encodedindex++] = PAD; } Encodeddata[encodedindex] = 0xa;
return new String (Encodeddata); /** * Decodes Base64 data into octects * * @param binarydata * Byte array containing Base64 data * @return
Array containind decoded data.
*/public static byte[] Decode (String encoded) {if (encoded = = NULL) return null;
char[] Base64data = Encoded.tochararray ();
Remove white spaces int len = Removewhitespace (base64data);
if (len% fourbyte!= 0) {return null;//should is divisible by four} int numberquadruple = (len/fourbyte);
if (numberquadruple = = 0) return to new byte[0];
byte decodeddata[] = null;
BYTE B1 = 0, b2 = 0, B3 = 0, b4 = 0, Marker0 = 0, marker1 = 0;
Char d1 = 0, d2 = 0, d3 = 0, d4 = 0;
int i = 0;
int encodedindex = 0;
int dataindex = 0;
Decodeddata = new byte[(numberquadruple) * 3]; for (; i < numberQuadruple-1; i++) {if (!isdata (D1 = base64data[dataindex++))) | |!isdata (d2 = Base64data[da taindex++]) | | !isdata (D3 = Base64data[dataindex++]) | |
!isdata ((D4 = base64data[dataindex++])) return null;//if found ' no data ' just return null B1 = Base64alphabet[d1];
b2 = Base64alphabet[d2];
B3 = Base64alphabet[d3];
B4 = base64alphabet[d4];
decodeddata[encodedindex++] = (byte) (B1 << 2 | b2 >> 4); decodeddata[encodedindex++] = (byte) ((B2 & 0xf) << 4) |
((B3 >> 2) & 0xf));
decodeddata[encodedindex++] = (byte) (B3 << 6 | b4); } if (!isdata (D1 = base64data[dataindex++)) | |!isdata ((d2 = base64data[dataindex++])) {return null;//if found
"No data" just return null} B1 = Base64alphabet[d1];
b2 = Base64alphabet[d2];
D3 = base64data[dataindex++];
D4 = base64data[dataindex++]; if (!isdata (d3)) | |!isdata ((d4)) {/Check if they are PAD characters if (Ispad (D3) && Ispad (D4)) {//two PA
D e.g. 3c[pad][pad] if ((B2 & 0xf)!= 0)//Last 4 bits should is zero return null;
byte[] tmp = new Byte[i * 3 + 1]; System.arraycopy (decodeDdata, 0, tmp, 0, I * 3);
Tmp[encodedindex] = (byte) (B1 << 2 | b2 >> 4);
return TMP;
else if (!ispad (D3) && Ispad (D4)) {//one PAD e.g. 3cq[pad] B3 = base64alphabet[d3];
if ((B3 & 0x3)!= 0)//last 2 bits should is zero return null;
byte[] tmp = new Byte[i * 3 + 2];
System.arraycopy (decodeddata, 0, tmp, 0, I * 3);
tmp[encodedindex++] = (byte) (B1 << 2 | b2 >> 4); Tmp[encodedindex] = (byte) ((B2 & 0xf) << 4) |
((B3 >> 2) & 0xf));
return TMP; else {return null;//a error like "3c[pad]r", "3cdX", "3cXd", "3cXX"//where X is non data}} else {//No
PAD e.g 3cQl B3 = base64alphabet[d3];
B4 = base64alphabet[d4];
decodeddata[encodedindex++] = (byte) (B1 << 2 | b2 >> 4); decodeddata[encodedindex++] = (byte) ((B2 & 0xf) << 4) |
((B3 >> 2) & 0xf));
decodeddata[encodedindex++] = (byte) (B3 << 6 | b4);
return decodeddata; }/** * Remove WhItespace from MIME containing encoded BASE64 data. * * @param data * The byte array of base64 data (with WS) * @return The new length */protected static int Remo
Vewhitespace (char[] data) {if (data = null) return 0;
Count characters that ' s not whitespace int newsize = 0;
int len = data.length;
for (int i = 0; i < len; i++) {if (!iswhitespace (Data[i])) data[newsize++] = Data[i];
return newsize;
public static void Main (string[] args) {System.out.println (Encode ("People's Republic of China". GetBytes ()); }
}