Java/Development Class/Base64

Материал из Java эксперт
Перейти к: навигация, поиск

Содержание

A Base64 Encoder/Decoder

   <source lang="java">
   

/*******************************************************************************

* 
* A Base64 Encoder/Decoder.
* 
* This class is used to encode and decode data in Base64 format as described in
* RFC 1521.
* 
*

* Copyright 2003: Christian d"Heureuse, Inventec Informatik AG, Switzerland.
* License: This is "Open Source" software and released under the
* * <p> * Version history:
* 2003-07-22 Christian d"Heureuse (chdh): Module created.
* 2005-08-11 chdh: Lincense changed from GPL to LGPL. * ******************************************************************************/ public class Base64Coder { // Mapping table from 6-bit nibbles to Base64 characters. private static char[] map1 = new char[64]; static { int i = 0; for (char c = "A"; c <= "Z"; c++) map1[i++] = c; for (char c = "a"; c <= "z"; c++) map1[i++] = c; for (char c = "0"; c <= "9"; c++) map1[i++] = c; map1[i++] = "+"; map1[i++] = "/"; } // Mapping table from Base64 characters to 6-bit nibbles. private static byte[] map2 = new byte[128]; static { for (int i = 0; i < map2.length; i++) map2[i] = -1; for (int i = 0; i < 64; i++) map2[map1[i]] = (byte) i; } /** * Encodes a string into Base64 format. No blanks or line breaks are inserted. * * @param s * a String to be encoded. * @return A String with the Base64 encoded data. */ public static String encode(String s) { return new String(encode(s.getBytes())); } /** * Encodes a byte array into Base64 format. No blanks or line breaks are * inserted. * * @param in * an array containing the data bytes to be encoded. * @return A character array with the Base64 encoded data. */ public static char[] encode(byte[] in) { int iLen = in.length; int oDataLen = (iLen * 4 + 2) / 3; // output length without padding int oLen = ((iLen + 2) / 3) * 4; // output length including padding char[] out = new char[oLen]; int ip = 0; int op = 0; while (ip < iLen) { int i0 = in[ip++] & 0xff; int i1 = ip < iLen ? in[ip++] & 0xff : 0; int i2 = ip < iLen ? in[ip++] & 0xff : 0; int o0 = i0 >>> 2; int o1 = ((i0 & 3) << 4) | (i1 >>> 4); int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6); int o3 = i2 & 0x3F; out[op++] = map1[o0]; out[op++] = map1[o1]; out[op] = op < oDataLen ? map1[o2] : "="; op++; out[op] = op < oDataLen ? map1[o3] : "="; op++; } return out; } /** * Decodes a Base64 string. * * @param s * a Base64 String to be decoded. * @return A String containing the decoded data. * @throws IllegalArgumentException * if the input is not valid Base64 encoded data. */ public static String decode(String s) { return new String(decode(s.toCharArray())); } /** * Decodes Base64 data. No blanks or line breaks are allowed within the Base64 * encoded data. * * @param in * a character array containing the Base64 encoded data. * @return An array containing the decoded data bytes. * @throws IllegalArgumentException * if the input is not valid Base64 encoded data. */ public static byte[] decode(char[] in) { int iLen = in.length; if (iLen % 4 != 0) throw new IllegalArgumentException( "Length of Base64 encoded input string is not a multiple of 4."); while (iLen > 0 && in[iLen - 1] == "=") iLen--; int oLen = (iLen * 3) / 4; byte[] out = new byte[oLen]; int ip = 0; int op = 0; while (ip < iLen) { int i0 = in[ip++]; int i1 = in[ip++]; int i2 = ip < iLen ? in[ip++] : "A"; int i3 = ip < iLen ? in[ip++] : "A"; if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127) throw new IllegalArgumentException("Illegal character in Base64 encoded data."); int b0 = map2[i0]; int b1 = map2[i1]; int b2 = map2[i2]; int b3 = map2[i3]; if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0) throw new IllegalArgumentException("Illegal character in Base64 encoded data."); int o0 = (b0 << 2) | (b1 >>> 4); int o1 = ((b1 & 0xf) << 4) | (b2 >>> 2); int o2 = ((b2 & 3) << 6) | b3; out[op++] = (byte) o0; if (op < oLen) out[op++] = (byte) o1; if (op < oLen) out[op++] = (byte) o2; } return out; } } </source>

A fast and memory efficient class to encode and decode to and from BASE64 in full accordance with RFC 2045

   <source lang="java">
   

import java.util.Arrays; /** A very fast and memory efficient class to encode and decode to and from BASE64 in full accordance

* with RFC 2045.

* On Windows XP sp1 with 1.4.2_04 and later ;), this encoder and decoder is about 10 times faster * on small arrays (10 - 1000 bytes) and 2-3 times as fast on larger arrays (10000 - 1000000 bytes) * compared to sun.misc.Encoder()/Decoder().

* * On byte arrays the encoder is about 20% faster than Jakarta Commons Base64 Codec for encode and * about 50% faster for decoding large arrays. This implementation is about twice as fast on very small * arrays (&lt 30 bytes). If source/destination is a String this * version is about three times as fast due to the fact that the Commons Codec result has to be recoded * to a String from byte[], which is very expensive.

* * This encode/decode algorithm doesn"t create any temporary arrays as many other codecs do, it only * allocates the resulting array. This produces less garbage and it is possible to handle arrays twice * as large as algorithms that create a temporary array. (E.g. Jakarta Commons Codec). It is unknown * whether Sun"s sun.misc.Encoder()/Decoder() produce temporary arrays but since performance * is quite low it probably does.

* * The encoder produces the same output as the Sun one except that the Sun"s encoder appends * a trailing line separator if the last character isn"t a pad. Unclear why but it only adds to the * length and is probably a side effect. Both are in conformance with RFC 2045 though.
* Commons codec seem to always att a trailing line separator.

* * Note! * The encode/decode method pairs (types) come in three versions with the exact same algorithm and * thus a lot of code redundancy. This is to not create any temporary arrays for transcoding to/from different * format types. The methods not used can simply be commented out.

* * There is also a "fast" version of all decode methods that works the same way as the normal ones, but * har a few demands on the decoded input. Normally though, these fast verions should be used if the source if * the input is known and it hasn"t bee tampered with.

* * If you find the code useful or you find a bug, please send me a note at base64 @ miginfocom . com. * * Licence (BSD): * * * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (base64 @ miginfocom . com) * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list * of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or other * materials provided with the distribution. * Neither the name of the MiG InfoCom AB nor the names of its contributors may be * used to endorse or promote products derived from this software without specific * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. * * @version 2.2 * @author Mikael Grev * Date: 2004-aug-02 * Time: 11:31:11 */

public class Base64 {

 private static final char[] CA = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray();
 private static final int[] IA = new int[256];
 static {
   Arrays.fill(IA, -1);
   for (int i = 0, iS = CA.length; i < iS; ++i) {
     IA[CA[i]] = i;
   }
   IA["="] = 0;
 }
 // ****************************************************************************************
 // *  char[] version
 // ****************************************************************************************
 /** Encodes a raw byte array into a BASE64 char[] representation i accordance with RFC 2045.
  * @param sArr The bytes to convert. If null or length 0 an empty array will be returned.
  * @param lineSep Optional "\r\n" after 76 characters, unless end of file.
* No line separator will be in breach of RFC 2045 which specifies max 76 per line but will be a * little faster. * @return A BASE64 encoded array. Never null. */ public final static char[] encodeToChar(byte[] sArr, boolean lineSep) { // Check special case int sLen = sArr != null ? sArr.length : 0; if (sLen == 0) { return new char[0]; } //assert sArr != null; int eLen = (sLen / 3) * 3; // Length of even 24-bits. int cCnt = ((sLen - 1) / 3 + 1) << 2; // Returned character count int dLen = cCnt + (lineSep ? (cCnt - 1) / 76 << 1 : 0); // Length of returned array char[] dArr = new char[dLen]; // Encode even 24-bits for (int s = 0, d = 0, cc = 0; s < eLen;) { // Copy next three bytes into lower 24 bits of int, paying attension to sign. int i = (sArr[s++] & 0xff) << 16 | (sArr[s++] & 0xff) << 8 | (sArr[s++] & 0xff); // Encode the int into four chars dArr[d++] = CA[(i >>> 18) & 0x3f]; dArr[d++] = CA[(i >>> 12) & 0x3f]; dArr[d++] = CA[(i >>> 6) & 0x3f]; dArr[d++] = CA[i & 0x3f]; // Add optional line separator if (lineSep && ++cc == 19 && d < dLen - 2) { dArr[d++] = "\r"; dArr[d++] = "\n"; cc = 0; } } // Pad and encode last bits if source isn"t even 24 bits. int left = sLen - eLen; // 0 - 2. if (left > 0) { // Prepare the int int i = ((sArr[eLen] & 0xff) << 10) | (left == 2 ? ((sArr[sLen - 1] & 0xff) << 2) : 0); // Set last four chars dArr[dLen - 4] = CA[i >> 12]; dArr[dLen - 3] = CA[(i >>> 6) & 0x3f]; dArr[dLen - 2] = left == 2 ? CA[i & 0x3f] : "="; dArr[dLen - 1] = "="; } return dArr; } /** Decodes a BASE64 encoded char array. All illegal characters will be ignored and can handle both arrays with * and without line separators. * @param sArr The source array. null or length 0 will return an empty array. * @return The decoded array of bytes. May be of length 0. Will be null if the legal characters * (including "=") isn"t divideable by 4. (I.e. definitely corrupted). */ public final static byte[] decode(char[] sArr) { // Check special case int sLen = sArr != null ? sArr.length : 0; if (sLen == 0) { return new byte[0]; } //assert sArr != null; // Count illegal characters (including "\r", "\n") to know what size the returned array will be, // so we don"t have to reallocate & copy it later. int sepCnt = 0; // Number of separator characters. (Actually illegal characters, but that"s a bonus...) for (int i = 0; i < sLen; ++i) { if (IA[sArr[i]] < 0) { ++sepCnt; } } // Check so that legal chars (including "=") are evenly divideable by 4 as specified in RFC 2045. if ((sLen - sepCnt) % 4 != 0) { return null; } int pad = 0; for (int i = sLen; i > 1 && IA[sArr[--i]] <= 0;) { if (sArr[i] == "=") { ++pad; } } int len = ((sLen - sepCnt) * 6 >> 3) - pad; byte[] dArr = new byte[len]; // Preallocate byte[] of exact length for (int s = 0, d = 0; d < len;) { // Assemble three bytes into an int from four "valid" characters. int i = 0; for (int j = 0; j < 4; ++j) { // j only increased if a valid char was found. int c = IA[sArr[s++]]; if (c >= 0) { i |= c << (18 - j * 6); } else { --j; } } // Add the bytes dArr[d++] = (byte) (i >> 16); if (d < len) { dArr[d++]= (byte) (i >> 8); if (d < len) { dArr[d++] = (byte) i; } } } return dArr; } /* * Decodes a BASE64 encoded char array that is known to be resonably well formatted. The method is about twice as * fast as {@link #decode(char[])}. The preconditions are:
* + The array must have a line length of 76 chars OR no line separators at all (one line).
* + Line separator must be "\r\n", as specified in RFC 2045 * + The array must not contain illegal characters within the encoded string
* + The array CAN have illegal characters at the beginning and end, those will be dealt with appropriately.
* @param sArr The source array. Length 0 will return an empty array. null will throw an exception. * @return The decoded array of bytes. May be of length 0. * / public final static byte[] decodeFast(char[] sArr) { // Check special case int sLen = sArr.length; if (sLen == 0) { return new byte[0]; } int sIx = 0, eIx = sLen - 1; // Start and end index after trimming. // Trim illegal chars from start while (sIx < eIx && IA[sArr[sIx]] < 0) { ++sIx; } // Trim illegal chars from end while (eIx > 0 && IA[sArr[eIx]] < 0) { --eIx; } // get the padding count (=) (0, 1 or 2) int pad = sArr[eIx] == "=" ? (sArr[eIx - 1] == "=" ? 2 : 1) : 0; // Count "=" at end. int cCnt = eIx - sIx + 1; // Content count including possible separators int sepCnt = sLen > 76 ? (sArr[76] == "\r" ? cCnt / 78 : 0) << 1 : 0; int len = ((cCnt - sepCnt) * 6 >> 3) - pad; // The number of decoded bytes byte[] dArr = new byte[len]; // Preallocate byte[] of exact length // Decode all but the last 0 - 2 bytes. int d = 0; for (int cc = 0, eLen = (len / 3) * 3; d < eLen;) { // Assemble three bytes into an int from four "valid" characters. int i = IA[sArr[sIx++]] << 18 | IA[sArr[sIx++]] << 12 | IA[sArr[sIx++]] << 6 | IA[sArr[sIx++]]; // Add the bytes dArr[d++] = (byte) (i >> 16); dArr[d++] = (byte) (i >> 8); dArr[d++] = (byte) i; // If line separator, jump over it. if (sepCnt > 0 && ++cc == 19) { sIx += 2; cc = 0; } } if (d < len) { // Decode last 1-3 bytes (incl "=") into 1-3 bytes int i = 0; for (int j = 0; sIx <= eIx - pad; ++j) { i |= IA[sArr[sIx++]] << (18 - j * 6); } for (int r = 16; d < len; r -= 8) { dArr[d++] = (byte) (i >> r); } } return dArr; }*/ // **************************************************************************************** // * byte[] version // **************************************************************************************** /** Encodes a raw byte array into a BASE64 byte[] representation i accordance with RFC 2045. * @param sArr The bytes to convert. If null or length 0 an empty array will be returned. * @param lineSep Optional "\r\n" after 76 characters, unless end of file.
* No line separator will be in breach of RFC 2045 which specifies max 76 per line but will be a * little faster. * @return A BASE64 encoded array. Never null. */ public final static byte[] encodeToByte(byte[] sArr, boolean lineSep) { // Check special case int sLen = sArr != null ? sArr.length : 0; if (sLen == 0) { return new byte[0]; } //assert sArr != null; int eLen = (sLen / 3) * 3; // Length of even 24-bits. int cCnt = ((sLen - 1) / 3 + 1) << 2; // Returned character count int dLen = cCnt + (lineSep ? (cCnt - 1) / 76 << 1 : 0); // Length of returned array byte[] dArr = new byte[dLen]; // Encode even 24-bits for (int s = 0, d = 0, cc = 0; s < eLen;) { // Copy next three bytes into lower 24 bits of int, paying attension to sign. int i = (sArr[s++] & 0xff) << 16 | (sArr[s++] & 0xff) << 8 | (sArr[s++] & 0xff); // Encode the int into four chars dArr[d++] = (byte) CA[(i >>> 18) & 0x3f]; dArr[d++] = (byte) CA[(i >>> 12) & 0x3f]; dArr[d++] = (byte) CA[(i >>> 6) & 0x3f]; dArr[d++] = (byte) CA[i & 0x3f]; // Add optional line separator if (lineSep && ++cc == 19 && d < dLen - 2) { dArr[d++] = "\r"; dArr[d++] = "\n"; cc = 0; } } // Pad and encode last bits if source isn"t an even 24 bits. int left = sLen - eLen; // 0 - 2. if (left > 0) { // Prepare the int int i = ((sArr[eLen] & 0xff) << 10) | (left == 2 ? ((sArr[sLen - 1] & 0xff) << 2) : 0); // Set last four chars dArr[dLen - 4] = (byte) CA[i >> 12]; dArr[dLen - 3] = (byte) CA[(i >>> 6) & 0x3f]; dArr[dLen - 2] = left == 2 ? (byte) CA[i & 0x3f] : (byte) "="; dArr[dLen - 1] = "="; } return dArr; } /** Decodes a BASE64 encoded byte array. All illegal characters will be ignored and can handle both arrays with * and without line separators. * @param sArr The source array. Length 0 will return an empty array. null will throw an exception. * @return The decoded array of bytes. May be of length 0. Will be null if the legal characters * (including "=") isn"t divideable by 4. (I.e. definitely corrupted). */ public final static byte[] decode(byte[] sArr) { // Check special case int sLen = sArr.length; // Count illegal characters (including "\r", "\n") to know what size the returned array will be, // so we don"t have to reallocate & copy it later. int sepCnt = 0; // Number of separator characters. (Actually illegal characters, but that"s a bonus...) for (int i = 0; i < sLen; ++i) { if (IA[sArr[i] & 0xff] < 0) { ++sepCnt; } } // Check so that legal chars (including "=") are evenly divideable by 4 as specified in RFC 2045. if ((sLen - sepCnt) % 4 != 0) { return null; } int pad = 0; for (int i = sLen; i > 1 && IA[sArr[--i] & 0xff] <= 0;) { if (sArr[i] == "=") { ++pad; } } int len = ((sLen - sepCnt) * 6 >> 3) - pad; byte[] dArr = new byte[len]; // Preallocate byte[] of exact length for (int s = 0, d = 0; d < len;) { // Assemble three bytes into an int from four "valid" characters. int i = 0; for (int j = 0; j < 4; ++j) { // j only increased if a valid char was found. int c = IA[sArr[s++] & 0xff]; if (c >= 0) { i |= c << (18 - j * 6); } else { --j; } } // Add the bytes dArr[d++] = (byte) (i >> 16); if (d < len) { dArr[d++]= (byte) (i >> 8); if (d < len) { dArr[d++] = (byte) i; } } } return dArr; }
 /* * Decodes a BASE64 encoded byte array that is known to be resonably well formatted. The method is about twice as
  * fast as {@link #decode(byte[])}. The preconditions are:
* + The array must have a line length of 76 chars OR no line separators at all (one line).
* + Line separator must be "\r\n", as specified in RFC 2045 * + The array must not contain illegal characters within the encoded string
* + The array CAN have illegal characters at the beginning and end, those will be dealt with appropriately.
* @param sArr The source array. Length 0 will return an empty array. null will throw an exception. * @return The decoded array of bytes. May be of length 0. * / public final static byte[] decodeFast(byte[] sArr) { // Check special case int sLen = sArr.length; if (sLen == 0) { return new byte[0]; } int sIx = 0, eIx = sLen - 1; // Start and end index after trimming. // Trim illegal chars from start while (sIx < eIx && IA[sArr[sIx] & 0xff] < 0) { ++sIx; } // Trim illegal chars from end while (eIx > 0 && IA[sArr[eIx] & 0xff] < 0) { --eIx; } // get the padding count (=) (0, 1 or 2) int pad = sArr[eIx] == "=" ? (sArr[eIx - 1] == "=" ? 2 : 1) : 0; // Count "=" at end. int cCnt = eIx - sIx + 1; // Content count including possible separators int sepCnt = sLen > 76 ? (sArr[76] == "\r" ? cCnt / 78 : 0) << 1 : 0; int len = ((cCnt - sepCnt) * 6 >> 3) - pad; // The number of decoded bytes byte[] dArr = new byte[len]; // Preallocate byte[] of exact length // Decode all but the last 0 - 2 bytes. int d = 0; for (int cc = 0, eLen = (len / 3) * 3; d < eLen;) { // Assemble three bytes into an int from four "valid" characters. int i = IA[sArr[sIx++]] << 18 | IA[sArr[sIx++]] << 12 | IA[sArr[sIx++]] << 6 | IA[sArr[sIx++]]; // Add the bytes dArr[d++] = (byte) (i >> 16); dArr[d++] = (byte) (i >> 8); dArr[d++] = (byte) i; // If line separator, jump over it. if (sepCnt > 0 && ++cc == 19) { sIx += 2; cc = 0; } } if (d < len) { // Decode last 1-3 bytes (incl "=") into 1-3 bytes int i = 0; for (int j = 0; sIx <= eIx - pad; ++j) { i |= IA[sArr[sIx++]] << (18 - j * 6); } for (int r = 16; d < len; r -= 8) { dArr[d++] = (byte) (i >> r); } } return dArr; }*/ // **************************************************************************************** // * String version // **************************************************************************************** /** Encodes a raw byte array into a BASE64 String representation i accordance with RFC 2045. * @param sArr The bytes to convert. If null or length 0 an empty array will be returned. * @param lineSep Optional "\r\n" after 76 characters, unless end of file.
* No line separator will be in breach of RFC 2045 which specifies max 76 per line but will be a * little faster. * @return A BASE64 encoded array. Never null. */ public final static String encodeToString(byte[] sArr, boolean lineSep) { // Reuse char[] since we can"t create a String incrementally anyway and StringBuffer/Builder would be slower. return new String(encodeToChar(sArr, lineSep)); } /** Decodes a BASE64 encoded String. All illegal characters will be ignored and can handle both strings with * and without line separators.
* Note! It can be up to about 2x the speed to call decode(str.toCharArray()) instead. That * will create a temporary array though. This version will use str.charAt(i) to iterate the string. * @param str The source string. null or length 0 will return an empty array. * @return The decoded array of bytes. May be of length 0. Will be null if the legal characters * (including "=") isn"t divideable by 4. (I.e. definitely corrupted). */ public final static byte[] decode(String str) { // Check special case int sLen = str != null ? str.length() : 0; if (sLen == 0) { return new byte[0]; } //assert str != null; // Count illegal characters (including "\r", "\n") to know what size the returned array will be, // so we don"t have to reallocate & copy it later. int sepCnt = 0; // Number of separator characters. (Actually illegal characters, but that"s a bonus...) for (int i = 0; i < sLen; ++i) { if (IA[str.charAt(i)] < 0) { ++sepCnt; } } // Check so that legal chars (including "=") are evenly divideable by 4 as specified in RFC 2045. if ((sLen - sepCnt) % 4 != 0) { return null; } // Count "=" at end int pad = 0; for (int i = sLen; i > 1 && IA[str.charAt(--i)] <= 0;) { if (str.charAt(i) == "=") { ++pad; } } int len = ((sLen - sepCnt) * 6 >> 3) - pad; byte[] dArr = new byte[len]; // Preallocate byte[] of exact length for (int s = 0, d = 0; d < len;) { // Assemble three bytes into an int from four "valid" characters. int i = 0; for (int j = 0; j < 4; ++j) { // j only increased if a valid char was found. int c = IA[str.charAt(s++)]; if (c >= 0) { i |= c << (18 - j * 6); } else { --j; } } // Add the bytes dArr[d++] = (byte) (i >> 16); if (d < len) { dArr[d++]= (byte) (i >> 8); if (d < len) { dArr[d++] = (byte) i; } } } return dArr; } /* * Decodes a BASE64 encoded string that is known to be resonably well formatted. The method is about twice as * fast as {@link #decode(String)}. The preconditions are:
* + The array must have a line length of 76 chars OR no line separators at all (one line).
* + Line separator must be "\r\n", as specified in RFC 2045 * + The array must not contain illegal characters within the encoded string
* + The array CAN have illegal characters at the beginning and end, those will be dealt with appropriately.
* @param s The source string. Length 0 will return an empty array. null will throw an exception. * @return The decoded array of bytes. May be of length 0. * / public final static byte[] decodeFast(String s) { // Check special case int sLen = s.length(); if (sLen == 0) { return new byte[0]; } int sIx = 0, eIx = sLen - 1; // Start and end index after trimming. // Trim illegal chars from start while (sIx < eIx && IA[s.charAt(sIx) & 0xff] < 0) { ++sIx; } // Trim illegal chars from end while (eIx > 0 && IA[s.charAt(eIx) & 0xff] < 0) { --eIx; } // get the padding count (=) (0, 1 or 2) int pad = s.charAt(eIx) == "=" ? (s.charAt(eIx - 1) == "=" ? 2 : 1) : 0; // Count "=" at end. int cCnt = eIx - sIx + 1; // Content count including possible separators int sepCnt = sLen > 76 ? (s.charAt(76) == "\r" ? cCnt / 78 : 0) << 1 : 0; int len = ((cCnt - sepCnt) * 6 >> 3) - pad; // The number of decoded bytes byte[] dArr = new byte[len]; // Preallocate byte[] of exact length // Decode all but the last 0 - 2 bytes. int d = 0; for (int cc = 0, eLen = (len / 3) * 3; d < eLen;) { // Assemble three bytes into an int from four "valid" characters. int i = IA[s.charAt(sIx++)] << 18 | IA[s.charAt(sIx++)] << 12 | IA[s.charAt(sIx++)] << 6 | IA[s.charAt(sIx++)]; // Add the bytes dArr[d++] = (byte) (i >> 16); dArr[d++] = (byte) (i >> 8); dArr[d++] = (byte) i; // If line separator, jump over it. if (sepCnt > 0 && ++cc == 19) { sIx += 2; cc = 0; } } if (d < len) { // Decode last 1-3 bytes (incl "=") into 1-3 bytes int i = 0; for (int j = 0; sIx <= eIx - pad; ++j) { i |= IA[s.charAt(sIx++)] << (18 - j * 6); } for (int r = 16; d < len; r -= 8) { dArr[d++] = (byte) (i >> r); } } return dArr; }*/

}



 </source>
   
  
 
  



array of byte to encode

   <source lang="java">
    

/* Copyright 2004 The Apache Software Foundation

*
*   Licensed under the Apache License, Version 2.0 (the "License");
*   you may not use this file except in compliance with the License.
*   You may obtain a copy of the License at
*
*       http://www.apache.org/licenses/LICENSE-2.0
*
*   Unless required by applicable law or agreed to in writing, software
*   distributed under the License is distributed on an "AS IS" BASIS,
*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*   See the License for the specific language governing permissions and
*  limitations under the License.
*/

//xmlbeans import java.io.UnsupportedEncodingException; /**

* format validation
*
* This class encodes/decodes hexadecimal data
* @author Jeffrey Rodriguez
* @version $Id: HexBin.java 125124 2005-01-14 00:23:54Z kkrouse $
*/

public class Main {

 static private final int  BASELENGTH   = 255;
 static private final int  LOOKUPLENGTH = 16;
 static private byte [] hexNumberTable    = new byte[BASELENGTH];
 static private byte [] lookUpHexAlphabet = new byte[LOOKUPLENGTH];
 static {
     for (int i = 0; i<BASELENGTH; i++ ) {
         hexNumberTable[i] = -1;
     }
     for ( int i = "9"; i >= "0"; i--) {
         hexNumberTable[i] = (byte) (i-"0");
     }
     for ( int i = "F"; i>= "A"; i--) {
         hexNumberTable[i] = (byte) ( i-"A" + 10 );
     }
     for ( int i = "f"; i>= "a"; i--) {
        hexNumberTable[i] = (byte) ( i-"a" + 10 );
     }
     for(int i = 0; i<10; i++ )
         lookUpHexAlphabet[i] = (byte) ("0"+i );
     for(int i = 10; i<=15; i++ )
         lookUpHexAlphabet[i] = (byte) ("A"+i -10);
 }
 /**
  * array of byte to encode
  *
  * @param binaryData
  * @return return encode binary array
  */
 static public byte[] encode(byte[] binaryData) {
     if (binaryData == null)
         return null;
     int lengthData   = binaryData.length;
     int lengthEncode = lengthData * 2;
     byte[] encodedData = new byte[lengthEncode];
     for( int i = 0; i<lengthData; i++ ){
         encodedData[i*2] = lookUpHexAlphabet[(binaryData[i] >> 4) & 0xf];
         encodedData[i*2+1] = lookUpHexAlphabet[ binaryData[i] & 0xf];
     }
     return encodedData;
 }

}



 </source>
   
  
 
  



Base64 Character encoder as specified in RFC1113

   <source lang="java">
   

/*

* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
* 
*      http://www.apache.org/licenses/LICENSE-2.0
* 
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id: Base64EncodeStream.java 447277 2006-09-18 06:19:34Z jeremias $ */

import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; /**

* This class implements a Base64 Character encoder as specified in RFC1113.
* Unlike some other encoding schemes there is nothing in this encoding
* that indicates where a buffer starts or ends.
*
* This means that the encoded text will simply start with the first line
* of encoded text and end with the last line of encoded text.
*
* @author 
* @author      Chuck McManis
* @version $Id: Base64EncodeStream.java 447277 2006-09-18 06:19:34Z jeremias $
*/

public class Base64EncodeStream extends OutputStream {

   /** This array maps the 6 bit values to their characters */
   private final static byte pem_array[] = {
   //   0   1   2   3   4   5   6   7
       "A","B","C","D","E","F","G","H", // 0
       "I","J","K","L","M","N","O","P", // 1
       "Q","R","S","T","U","V","W","X", // 2
       "Y","Z","a","b","c","d","e","f", // 3
       "g","h","i","j","k","l","m","n", // 4
       "o","p","q","r","s","t","u","v", // 5
       "w","x","y","z","0","1","2","3", // 6
       "4","5","6","7","8","9","+","/"  // 7
   };
   byte [] atom = new byte[3];
   int     atomLen = 0;
   byte [] encodeBuf = new byte[4];
   int     lineLen = 0;
   PrintStream  out;
   boolean closeOutOnClose;
   public Base64EncodeStream(OutputStream out) {
       this.out = new PrintStream(out);
       closeOutOnClose = true;
   }
   public Base64EncodeStream(OutputStream out, boolean closeOutOnClose) {
       this.out = new PrintStream(out);
       this.closeOutOnClose = closeOutOnClose;
   }
   public void close () throws IOException {
       if (out != null) {
           encodeAtom();
           out.flush();        
           if (closeOutOnClose)
               out.close();
           out=null;
       }
   }
   /**
    * This can"t really flush out output since that may generate
    * "=" chars which would indicate the end of the stream.
    * Instead we flush out.  You can only be sure all output is 
    * writen by closing this stream.
    */
   public void flush() throws IOException {
       out.flush();
   }
   public void write(int b) throws IOException {
       atom[atomLen++] = (byte)b;
       if (atomLen == 3)
           encodeAtom();
   }
   public void write(byte []data) throws IOException {
       encodeFromArray(data, 0, data.length);
   }
   public void write(byte [] data, int off, int len) throws IOException {
       encodeFromArray(data, off, len);
   }
   /**
    * enocodeAtom - Take three bytes of input and encode it as 4
    * printable characters. Note that if the length in len is less
    * than three is encodes either one or two "=" signs to indicate
    * padding characters.
    */
   void encodeAtom() throws IOException {
       byte a, b, c;
       switch (atomLen) {
       case 0: return;
       case 1:
           a = atom[0];
           encodeBuf[0] = pem_array[((a >>> 2) & 0x3F)];
           encodeBuf[1] = pem_array[((a <<  4) & 0x30)];
           encodeBuf[2] = encodeBuf[3] = "=";
           break;
       case 2:
           a = atom[0];
           b = atom[1];
           encodeBuf[0] = pem_array[((a >>> 2) & 0x3F)];
           encodeBuf[1] = pem_array[(((a << 4) & 0x30) | ((b >>> 4) & 0x0F))];
           encodeBuf[2] = pem_array[((b  << 2) & 0x3C)];
           encodeBuf[3] = "=";
           break;
       default:
           a = atom[0];
           b = atom[1];
           c = atom[2];
           encodeBuf[0] = pem_array[((a >>> 2) & 0x3F)];
           encodeBuf[1] = pem_array[(((a << 4) & 0x30) | ((b >>> 4) & 0x0F))];
           encodeBuf[2] = pem_array[(((b << 2) & 0x3C) | ((c >>> 6) & 0x03))];
           encodeBuf[3] = pem_array[c & 0x3F];
       }
       if (lineLen == 64) {
           out.println();
           lineLen = 0;
       }
       out.write(encodeBuf);
       lineLen += 4;
       atomLen = 0;
   }
   /**
    * enocodeAtom - Take three bytes of input and encode it as 4
    * printable characters. Note that if the length in len is less
    * than three is encodes either one or two "=" signs to indicate
    * padding characters.
    */
   void encodeFromArray(byte[] data, int offset, int len) 
       throws IOException{
       byte a, b, c;
       if (len == 0)
           return;
       // System.out.println("atomLen: " + atomLen + 
       //                    " len: " + len + 
       //                    " offset:  " + offset);
       if (atomLen != 0) {
           switch(atomLen) {
           case 1:
               atom[1] = data[offset++]; len--; atomLen++;
               if (len == 0) return;
               atom[2] = data[offset++]; len--; atomLen++;
               break;
           case 2:
               atom[2] = data[offset++]; len--; atomLen++;
               break;
           default:
           }
           encodeAtom();
       }
       while (len >=3) {
           a = data[offset++];
           b = data[offset++];
           c = data[offset++];
           
           encodeBuf[0] = pem_array[((a >>> 2) & 0x3F)];
           encodeBuf[1] = pem_array[(((a << 4) & 0x30) | ((b >>> 4) & 0x0F))];
           encodeBuf[2] = pem_array[(((b << 2) & 0x3C) | ((c >>> 6) & 0x03))];
           encodeBuf[3] = pem_array[c & 0x3F];
           out.write(encodeBuf);
           lineLen += 4;
           if (lineLen == 64) {
               out.println();
               lineLen = 0;
           }
           len -=3;
       }
       switch (len) {
       case 1:
           atom[0] = data[offset];
           break;
       case 2:
           atom[0] = data[offset];
           atom[1] = data[offset+1];
           break;
       default:
       }
       atomLen = len;
   }
   
   

}



 </source>
   
  
 
  



Base64 encoder/decoder

   <source lang="java">
   

/*************************************************************** Copyright (c) 1998, 1999 Nate Sammons <nate@protomatter.ru> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Contact support@protomatter.ru with your questions, comments, gripes, praise, etc...

                                                                                                                              • /

/***************************************************************

 - moved to the net.matuschek.util tree by Daniel Matuschek
 - replaced deprecated getBytes() method in method decode
 - added String encode(String) method to encode a String to 
   base64
***************************************************************/

/**

* Base64 encoder/decoder.  Does not stream, so be careful with
* using large amounts of data
*
* @author Nate Sammons
* @author Daniel Matuschek
* @version $Id: Base64.java,v 1.4 2001/04/17 10:09:27 matuschd Exp $
*/

public class Base64 {

 private Base64()
 {
   super();
 }
 /**
  *  Encode some data and return a String.
  */
 public final static String encode(byte[] d)
 {
   if (d == null) return null;
   byte data[] = new byte[d.length+2];
   System.arraycopy(d, 0, data, 0, d.length);
   byte dest[] = new byte[(data.length/3)*4];
   // 3-byte to 4-byte conversion
   for (int sidx = 0, didx=0; sidx < d.length; sidx += 3, didx += 4)
   {
     dest[didx]   = (byte) ((data[sidx] >>> 2) & 077);
     dest[didx+1] = (byte) ((data[sidx+1] >>> 4) & 017 |
                 (data[sidx] << 4) & 077);
     dest[didx+2] = (byte) ((data[sidx+2] >>> 6) & 003 |
                 (data[sidx+1] << 2) & 077);
     dest[didx+3] = (byte) (data[sidx+2] & 077);
   }
   // 0-63 to ascii printable conversion
   for (int idx = 0; idx <dest.length; idx++)
   {
     if (dest[idx] < 26)     dest[idx] = (byte)(dest[idx] + "A");
     else if (dest[idx] < 52)  dest[idx] = (byte)(dest[idx] + "a" - 26);
     else if (dest[idx] < 62)  dest[idx] = (byte)(dest[idx] + "0" - 52);
     else if (dest[idx] < 63)  dest[idx] = (byte)"+";
     else            dest[idx] = (byte)"/";
   }
   // add padding
   for (int idx = dest.length-1; idx > (d.length*4)/3; idx--)
   {
     dest[idx] = (byte)"=";
   }
   return new String(dest);
 }
 /**
  * Encode a String using Base64 using the default platform encoding
  **/
 public final static String encode(String s) {
   return encode(s.getBytes());
 }
 /**
  *  Decode data and return bytes.
  */
 public final static byte[] decode(String str)
 {
   if (str == null)  return  null;
   byte data[] = str.getBytes();
   return decode(data);
 }
 /**
  *  Decode data and return bytes.  Assumes that the data passed
  *  in is ASCII text.
  */
 public final static byte[] decode(byte[] data)
 {
   int tail = data.length;
   while (data[tail-1] == "=")  tail--;
   byte dest[] = new byte[tail - data.length/4];
   // ascii printable to 0-63 conversion
   for (int idx = 0; idx <data.length; idx++)
   {
     if (data[idx] == "=")    data[idx] = 0;
     else if (data[idx] == "/") data[idx] = 63;
     else if (data[idx] == "+") data[idx] = 62;
     else if (data[idx] >= "0"  &&  data[idx] <= "9")
       data[idx] = (byte)(data[idx] - ("0" - 52));
     else if (data[idx] >= "a"  &&  data[idx] <= "z")
       data[idx] = (byte)(data[idx] - ("a" - 26));
     else if (data[idx] >= "A"  &&  data[idx] <= "Z")
       data[idx] = (byte)(data[idx] - "A");
   }
   // 4-byte to 3-byte conversion
   int sidx, didx;
   for (sidx = 0, didx=0; didx < dest.length-2; sidx += 4, didx += 3)
   {
     dest[didx]   = (byte) ( ((data[sidx] << 2) & 255) |
             ((data[sidx+1] >>> 4) & 3) );
     dest[didx+1] = (byte) ( ((data[sidx+1] << 4) & 255) |
             ((data[sidx+2] >>> 2) & 017) );
     dest[didx+2] = (byte) ( ((data[sidx+2] << 6) & 255) |
             (data[sidx+3] & 077) );
   }
   if (didx < dest.length)
   {
     dest[didx]   = (byte) ( ((data[sidx] << 2) & 255) |
             ((data[sidx+1] >>> 4) & 3) );
   }
   if (++didx < dest.length)
   {
     dest[didx]   = (byte) ( ((data[sidx+1] << 4) & 255) |
             ((data[sidx+2] >>> 2) & 017) );
   }
   return dest;
 }
 /**
  *  A simple test that encodes and decodes the first commandline argument.
  */
 public static final void main(String[] args)
 {
   if (args.length != 1)
   {
     System.out.println("Usage: Base64 string");
     System.exit(0);
   }
   try
   {
     String e = Base64.encode(args[0].getBytes());
     String d = new String(Base64.decode(e));
     System.out.println("Input   = "" + args[0] + """);
     System.out.println("Encoded = "" + e + """);
     System.out.println("Decoded = "" + d + """);
   }
   catch (Exception x)
   {
     x.printStackTrace();
   }
 }

}



 </source>
   
  
 
  



BASE64 encoder implementation

   <source lang="java">
   

/*

* Copyright � World Wide Web Consortium, (Massachusetts Institute of Technology, 
* Institut National de Recherche en Informatique et en Automatique, Keio University).
* All Rights Reserved. http://www.w3.org/Consortium/Legal/
*/

import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; /**

* BASE64 encoder implementation.
* This object takes as parameter an input stream and an output stream. It
* encodes the input stream, using the BASE64 encoding rules, as defined
* in 
* and emit the resulting data to the output stream.
* @see org.w3c.tools.codec.Base64Decoder
*/

public class Base64Encoder {

 private static final int BUFFER_SIZE = 1024;
 private static byte encoding[] =
   {
     (byte) "A", (byte) "B", (byte) "C", (byte) "D", (byte) "E", (byte) "F", (byte) "G", (byte) "H", // 0-7
     (byte) "I", (byte) "J", (byte) "K", (byte) "L", (byte) "M", (byte) "N", (byte) "O", (byte) "P", // 8-15
     (byte) "Q", (byte) "R", (byte) "S", (byte) "T", (byte) "U", (byte) "V", (byte) "W", (byte) "X", // 16-23
     (byte) "Y", (byte) "Z", (byte) "a", (byte) "b", (byte) "c", (byte) "d", (byte) "e", (byte) "f", // 24-31
     (byte) "g", (byte) "h", (byte) "i", (byte) "j", (byte) "k", (byte) "l", (byte) "m", (byte) "n", // 32-39
     (byte) "o", (byte) "p", (byte) "q", (byte) "r", (byte) "s", (byte) "t", (byte) "u", (byte) "v", // 40-47
     (byte) "w", (byte) "x", (byte) "y", (byte) "z", (byte) "0", (byte) "1", (byte) "2", (byte) "3", // 48-55
     (byte) "4", (byte) "5", (byte) "6", (byte) "7", (byte) "8", (byte) "9", (byte) "+", (byte) "/", // 56-63
     (byte) "=" // 64
 };
 InputStream in = null;
 OutputStream out = null;
 boolean stringp = false;
 private final int get1(byte buf[], int off)
 {
   return (buf[off] & 0xfc) >> 2;
 }
 private final int get2(byte buf[], int off)
 {
   return ((buf[off] & 0x3) << 4) | ((buf[off + 1] & 0xf0) >>> 4);
 }
 private final int get3(byte buf[], int off)
 {
   return ((buf[off + 1] & 0x0f) << 2) | ((buf[off + 2] & 0xc0) >>> 6);
 }
 private static final int get4(byte buf[], int off)
 {
   return buf[off + 2] & 0x3f;
 }
 /**
  * Process the data: encode the input stream to the output stream.
  * This method runs through the input stream, encoding it to the output 
  * stream.
  * @exception IOException If we weren"t able to access the input stream or
  *    the output stream.
  */
 public void process() throws IOException
 {
   byte buffer[] = new byte[BUFFER_SIZE];
   int got = -1;
   int off = 0;
   int count = 0;
   while ((got = in.read(buffer, off, BUFFER_SIZE - off)) > 0)
   {
     if (got >= 3)
     {
       got += off;
       off = 0;
       while (off + 3 <= got)
       {
         int c1 = get1(buffer, off);
         int c2 = get2(buffer, off);
         int c3 = get3(buffer, off);
         int c4 = get4(buffer, off);
         switch (count)
         {
           case 73 :
             out.write(encoding[c1]);
             out.write(encoding[c2]);
             out.write(encoding[c3]);
             out.write("\n");
             out.write(encoding[c4]);
             count = 1;
             break;
           case 74 :
             out.write(encoding[c1]);
             out.write(encoding[c2]);
             out.write("\n");
             out.write(encoding[c3]);
             out.write(encoding[c4]);
             count = 2;
             break;
           case 75 :
             out.write(encoding[c1]);
             out.write("\n");
             out.write(encoding[c2]);
             out.write(encoding[c3]);
             out.write(encoding[c4]);
             count = 3;
             break;
           case 76 :
             out.write("\n");
             out.write(encoding[c1]);
             out.write(encoding[c2]);
             out.write(encoding[c3]);
             out.write(encoding[c4]);
             count = 4;
             break;
           default :
             out.write(encoding[c1]);
             out.write(encoding[c2]);
             out.write(encoding[c3]);
             out.write(encoding[c4]);
             count += 4;
             break;
         }
         off += 3;
       }
       // Copy remaining bytes to beginning of buffer:
       for (int i = 0; i < 3; i++)
         buffer[i] = (i < got - off) ? buffer[off + i] : ((byte) 0);
       off = got - off;
     }
     else
     {
       // Total read amount is less then 3 bytes:
       off += got;
     }
   }
   // Manage the last bytes, from 0 to off:
   switch (off)
   {
     case 1 :
       out.write(encoding[get1(buffer, 0)]);
       out.write(encoding[get2(buffer, 0)]);
       out.write("=");
       out.write("=");
       break;
     case 2 :
       out.write(encoding[get1(buffer, 0)]);
       out.write(encoding[get2(buffer, 0)]);
       out.write(encoding[get3(buffer, 0)]);
       out.write("=");
   }
   return;
 }
 /**
  * Encode the content of this encoder, as a string.
  * This methods encode the String content, that was provided at creation 
  * time, following the BASE64 rules, as specified in the rfc1521.
  * @return A String, reprenting the encoded content of the input String.
  */
 public String processString()
 {
   if (!stringp)
     throw new RuntimeException(
       this.getClass().getName()
         + "[processString]"
         + "invalid call (not a String)");
   try
   {
     process();
   }
   catch (IOException e)
   {
   }
   return ((ByteArrayOutputStream) out).toString();
 }
 /**
  * Create a new Base64 encoder, to encode the given string.
  * @param input The String to be encoded.
  */
 public Base64Encoder(String input)
 {
   byte bytes[];
   try
   {
     bytes = input.getBytes("ISO-8859-1");
   }
   catch (UnsupportedEncodingException ex)
   {
     throw new RuntimeException(
       this.getClass().getName()
         + "[Constructor] Unable to convert"
         + "properly char to bytes");
   }
   this.stringp = true;
   this.in = new ByteArrayInputStream(bytes);
   this.out = new ByteArrayOutputStream();
 }
 /**
  * Create a new Base64 encoder, encoding input to output.
  * @param in The input stream to be encoded.
  * @param out The output stream, to write encoded data to.
  */
 public Base64Encoder(InputStream in, OutputStream out)
 {
   this.in = in;
   this.out = out;
   this.stringp = false;
 }
 /**
  * Testing the encoder.
  * Run with one argument, prints the encoded version of it.
  */
 public static void main(String args[])
 {
   if (args.length != 1)
   {
     System.out.println("Base64Encoder <string>");
     System.exit(0);
   }
   Base64Encoder b = new Base64Encoder(args[0]);
   System.out.println("[" + b.processString() + "]");
   // joe:eoj -> am9lOmVvag==
   // 12345678:87654321 -> MTIzNDU2Nzg6ODc2NTQzMjE=
 }

}



 </source>
   
  
 
  



Base-64 Encoder - translates from base-64 text into binary

   <source lang="java">
   

/*

* Base64Encoder.java
*
* Created on 20 December 2005, 11:15
*
*/

import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.nio.charset.CoderResult; /**

* <p>Base-64 Encoder - translates from base-64 text into binary.

*

Whitespace is ignored, so is anything following a terminating = * character.

* @author Malcolm McMahon
* @version $Revision: 1.1 $
*/

public class Base64Encoder extends CharsetEncoder {

   final static int CHARCODE_INVALID = -1;
   final static int CHARCODE_PADDER = -2;
   final static int CHARCODE_WHITESPACE = -3;
   
   int[] encTable;
   int encState;
   Byte excessByte;
   int bits;
   /** Creates a new instance of Base64Encoder
    * @param cs The Charset which created this
    * @param encTable Table which maps chacacters onto 6 bit values.
    */
   public Base64Encoder(Charset cs, int[] encTable) {
       super(cs, 1.4f, 2f);
       this.encTable = encTable;
   }
   
   private boolean out(ByteBuffer bb, int outValue) {
       if(bb.remaining() > 0) {
           bb.put((byte)outValue);
           return true;
       } else {
           excessByte = Byte.valueOf((byte)outValue);
           return false;
       }
   }
   
   
   
   
   /**
    * Flushes this encoder.
    *
*

The default implementation of this method does nothing, and always * returns {@link CoderResult#UNDERFLOW}. This method should be overridden * by encoders that may need to write final bytes to the output buffer * once the entire input sequence has been read.

    *
    * @param  out
    *         The output byte buffer
    *
    * @return  A coder-result object, either {@link CoderResult#UNDERFLOW} or
    *          {@link CoderResult#OVERFLOW}
    */
   protected java.nio.charset.CoderResult implFlush(java.nio.ByteBuffer out) {
       if(encState != 0 && encState != 4)
           throw new IllegalArgumentException("Base-64 text ends prematurely");
       if(excessByte == null) {
           implReset();
           return CoderResult.UNDERFLOW;
       }
       if(out.remaining() > 0) {
           out.put(excessByte.byteValue());
           implReset();
           return CoderResult.UNDERFLOW;
       } else
           return CoderResult.OVERFLOW;
       
   }
   
   /**
    * Encodes one or more characters into one or more bytes.
    *
*

This method encapsulates the basic encoding loop, encoding as many * characters as possible until it either runs out of input, runs out of room * in the output buffer, or encounters an encoding error. This method is * invoked by the {@link #encode encode} method, which handles result * interpretation and error recovery. * * <p> The buffers are read from, and written to, starting at their current * positions. At most {@link Buffer#remaining in.remaining()} characters * will be read, and at most {@link Buffer#remaining out.remaining()} * bytes will be written. The buffers" positions will be advanced to * reflect the characters read and the bytes written, but their marks and * limits will not be modified. * * <p> This method returns a {@link CoderResult} object to describe its * reason for termination, in the same manner as the {@link #encode encode} * method. Most implementations of this method will handle encoding errors * by returning an appropriate result object for interpretation by the * {@link #encode encode} method. An optimized implementation may instead * examine the relevant error action and implement that action itself. * * <p> An implementation of this method may perform arbitrary lookahead by * returning {@link CoderResult#UNDERFLOW} until it receives sufficient * input.

    *
    * @param  in
    *         The input character buffer
    *
    * @param  out
    *         The output byte buffer
    *
    * @return  A coder-result object describing the reason for termination
    */
   public java.nio.charset.CoderResult encodeLoop(java.nio.CharBuffer in, java.nio.ByteBuffer out) {
       if(excessByte != null) {
           if(out.remaining() > 0) {
               out.put(excessByte.byteValue());
               excessByte = null;
           } else
               return CoderResult.OVERFLOW;
           
       }
       while(in.remaining() > 0) {
           char inch = in.get();
           int code = (int)inch >= encTable.length ? CHARCODE_INVALID : encTable[(int)inch];
           if(encState < 4) {
               switch(code) {
                   case CHARCODE_INVALID:
                       throw new IllegalArgumentException("Invalid base-64 character"" + inch + """ );
                   case CHARCODE_WHITESPACE:
                       break;
                   case CHARCODE_PADDER:
                       if(encState == 1)
                           throw new IllegalArgumentException("Mal-formed base-64 (= after one character");
                       encState = 4;
                       break;
                   default:
                       switch(encState) {
                           case 0:
                               bits = code << 2;
                               encState = 1;
                               break;
                           case 1:
                               encState = 2;
                               int v = bits | ((code >> 4) & 3);
                               bits = (code << 4) & 0xF0;
                               if(!out(out, v))
                                   return CoderResult.OVERFLOW;
                               break;
                           case 2:
                               encState = 3;
                               v = bits | (code >> 2) & 0x0f;
                               bits = (code << 6) & 0xC0;
                               if(!out(out, v))
                                   return CoderResult.OVERFLOW;
                               break;
                           case 3:
                               encState = 0;
                               bits |= (code & 0x3f);
                               if(!out(out, bits))
                                   return CoderResult.OVERFLOW;
                               break;
                       }
                       
                       break;
               }
               
               
           }
       }
       return CoderResult.UNDERFLOW;
   }
   /**
    * Reset - clear encoder state
    */
   protected void implReset() {
       encState = 0;
       bits = 0;
       excessByte = null;
   }
   

}



 </source>
   
  
 
  



Base64 encoding/decoding.

   <source lang="java">
   

/*

* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common
* Development and Distribution License("CDDL") (collectively, the
* "License"). You may not use this file except in compliance with the
* License. You can obtain a copy of the License at
* http://www.netbeans.org/cddl-gplv2.html
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
* specific language governing permissions and limitations under the
* License.  When distributing the software, include this License Header
* Notice in each file and include the License file at
* nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the
* License Header, with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* Contributor(s):
*
* The Original Software is NetBeans. The Initial Developer of the Original
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
* Microsystems, Inc. All Rights Reserved.
*
* If you wish your version of this file to be governed by only the CDDL
* or only the GPL Version 2, indicate your decision by adding
* "[Contributor] elects to include this software in this distribution
* under the [CDDL or GPL Version 2] license." If you do not indicate a
* single choice of license, a recipient has the option to distribute
* your version of this file under either the CDDL, the GPL Version 2 or
* to extend the choice of license to its licensees as provided above.
* However, if you add GPL Version 2 code and therefore, elected the GPL
* Version 2 license, then the option applies only if the new code is
* made subject to such option by the copyright holder.
*/

/** This class provides Base64 encoding/decoding.

*/

public class Base64 {

   private Base64()
   {
       //Avoid instantiation of this class
   }
   
   /** Encodes datas using base64 encoding.
    * @param abyte0 data for encoding
    * @return encoded string
    */
   static String encode(final byte abyte0[])
   {
       final StringBuffer stringbuffer = new StringBuffer();
       for(int i = 0; i < abyte0.length; i += 3)
           stringbuffer.append(encodeBlock(abyte0, i));
       
       return stringbuffer.toString();
   }
   
   private static char[] encodeBlock(final byte abyte0[], final int i)
   {
       int j = 0;
       final int k = abyte0.length - i - 1;
       final int l = k < 2 ? k : 2;
       for(int i1 = 0; i1 <= l; i1++)
       {
           final byte byte0 = abyte0[i + i1];
           final int j1 = byte0 >= 0 ? ((int) (byte0)) : byte0 + 256;
           j += j1 << 8 * (2 - i1);
       }
       
       char ac[] = new char[4];
       for(int k1 = 0; k1 < 4; k1++)
       {
           final int l1 = j >>> 6 * (3 - k1) & 0x3f;
           ac[k1] = getChar(l1);
       }
       
       if(k < 1)
           ac[2] = "=";
       if(k < 2)
           ac[3] = "=";
       return ac;
   }
   
   private static char getChar(final int i)
   {
       if(i >= 0 && i <= 25)
           return (char)(65 + i);
       if(i >= 26 && i <= 51)
           return (char)(97 + (i - 26));
       if(i >= 52 && i <= 61)
           return (char)(48 + (i - 52));
       if(i == 62)
           return "+";
       return i != 63 ? "?" : "/";
   }
   
   /** Decode string using Base64 encoding.
    * @param s string for decoding
    * @return decoded data
    */
   static byte[] decode(final String s)
   {
       if (s.length() == 0) return new byte[0];
       int i = 0;
       for(int j = s.length() - 1; j > 0 && s.charAt(j) == "="; j--)
           i++;
       
       final int k = (s.length() * 6) / 8 - i;
       byte abyte0[] = new byte[k];
       int l = 0;
       for(int i1 = 0; i1 < s.length(); i1 += 4)
       {
           final int j1 = (getValue(s.charAt(i1)) << 18) + (getValue(s.charAt(i1 + 1)) << 12) + (getValue(s.charAt(i1 + 2)) << 6) + getValue(s.charAt(i1 + 3));
           for(int k1 = 0; k1 < 3 && l + k1 < abyte0.length; k1++)
               abyte0[l + k1] = (byte)(j1 >> 8 * (2 - k1) & 0xff);
           
           l += 3;
       }
       return abyte0;
   }
   
   private static int getValue(final char c)
   {
       if(c >= "A" && c <= "Z")
           return c - 65;
       if(c >= "a" && c <= "z")
           return (c - 97) + 26;
       if(c >= "0" && c <= "9")
           return (c - 48) + 52;
       if(c == "+")
           return 62;
       if(c == "/")
           return 63;
       return c != "=" ? -1 : 0;
   }

}



 </source>
   
  
 
  



Base64 from by Funambol, Inc.

   <source lang="java">
   

/*

* Funambol is a mobile platform developed by Funambol, Inc. 
* Copyright (C) 2003 - 2007 Funambol, Inc.
* 
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by
* the Free Software Foundation with the addition of the following permission 
* added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
* WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE 
* WARRANTY OF NON INFRINGEMENT  OF THIRD PARTY RIGHTS.
* 
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
* details.
* 
* You should have received a copy of the GNU Affero General Public License 
* along with this program; if not, see http://www.gnu.org/licenses or write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA.
* 
* You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite 
* 305, Redwood City, CA 94063, USA, or at email address info@funambol.ru.
* 
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
* 
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Powered by Funambol" logo. If the display of the logo is not reasonably 
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Powered by Funambol". 
*/

import java.io.UnsupportedEncodingException; public class Base64 {

   private static final byte[] encodingTable =
       { (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)"/" };
   /**
    * encode the input data producong a base 64 encoded byte array.
    * 
    * @return a byte array containing the base 64 encoded data.
    */
   public static byte[] encode(byte[] data) {
       byte[] bytes;
       int modulus = data.length % 3;
       if (modulus == 0) {
           bytes = new byte[4 * data.length / 3];
       } else {
           bytes = new byte[4 * ((data.length / 3) + 1)];
       }
       int dataLength = (data.length - modulus);
       int a1, a2, a3;
       for (int i = 0, j = 0; i < dataLength; i += 3, j += 4) {
           a1 = data[i] & 0xff;
           a2 = data[i + 1] & 0xff;
           a3 = data[i + 2] & 0xff;
           bytes[j] = encodingTable[(a1 >>> 2) & 0x3f];
           bytes[j + 1] = encodingTable[((a1 << 4) | (a2 >>> 4)) & 0x3f];
           bytes[j + 2] = encodingTable[((a2 << 2) | (a3 >>> 6)) & 0x3f];
           bytes[j + 3] = encodingTable[a3 & 0x3f];
       }
       /*
        * process the tail end.
        */
       int b1, b2, b3;
       int d1, d2;
       switch (modulus) {
           case 0: /* nothing left to do */
               break;
           case 1:
               d1 = data[data.length - 1] & 0xff;
               b1 = (d1 >>> 2) & 0x3f;
               b2 = (d1 << 4) & 0x3f;
               bytes[bytes.length - 4] = encodingTable[b1];
               bytes[bytes.length - 3] = encodingTable[b2];
               bytes[bytes.length - 2] = (byte)"=";
               bytes[bytes.length - 1] = (byte)"=";
               break;
           case 2:
               d1 = data[data.length - 2] & 0xff;
               d2 = data[data.length - 1] & 0xff;
               b1 = (d1 >>> 2) & 0x3f;
               b2 = ((d1 << 4) | (d2 >>> 4)) & 0x3f;
               b3 = (d2 << 2) & 0x3f;
               bytes[bytes.length - 4] = encodingTable[b1];
               bytes[bytes.length - 3] = encodingTable[b2];
               bytes[bytes.length - 2] = encodingTable[b3];
               bytes[bytes.length - 1] = (byte)"=";
               break;
       }
       return bytes;
   }
   /*
    * set up the decoding table.
    */
   private static final byte[] decodingTable;
   static {
       decodingTable = new byte[128];
       for (int i = 0; i < 128; i++) {
           decodingTable[i] = (byte)-1;
       }
       for (int i = "A"; i <= "Z"; i++) {
           decodingTable[i] = (byte)(i - "A");
       }
       for (int i = "a"; i <= "z"; i++) {
           decodingTable[i] = (byte)(i - "a" + 26);
       }
       for (int i = "0"; i <= "9"; i++) {
           decodingTable[i] = (byte)(i - "0" + 52);
       }
       decodingTable["+"] = 62;
       decodingTable["/"] = 63;
   }
   /**
    * decode the base 64 encoded input data.
    * 
    * @return a byte array representing the decoded data.
    */
   public static byte[] decode(byte[] data) {
       byte[] bytes;
       byte b1, b2, b3, b4;
       data = discardNonBase64Bytes(data);
       if (data[data.length - 2] == "=") {
           bytes = new byte[(((data.length / 4) - 1) * 3) + 1];
       } else if (data[data.length - 1] == "=") {
           bytes = new byte[(((data.length / 4) - 1) * 3) + 2];
       } else {
           bytes = new byte[((data.length / 4) * 3)];
       }
       for (int i = 0, j = 0; i < data.length - 4; i += 4, j += 3) {
           b1 = decodingTable[data[i]];
           b2 = decodingTable[data[i + 1]];
           b3 = decodingTable[data[i + 2]];
           b4 = decodingTable[data[i + 3]];
           bytes[j] = (byte)((b1 << 2) | (b2 >> 4));
           bytes[j + 1] = (byte)((b2 << 4) | (b3 >> 2));
           bytes[j + 2] = (byte)((b3 << 6) | b4);
       }
       if (data[data.length - 2] == "=") {
           b1 = decodingTable[data[data.length - 4]];
           b2 = decodingTable[data[data.length - 3]];
           bytes[bytes.length - 1] = (byte)((b1 << 2) | (b2 >> 4));
       } else if (data[data.length - 1] == "=") {
           b1 = decodingTable[data[data.length - 4]];
           b2 = decodingTable[data[data.length - 3]];
           b3 = decodingTable[data[data.length - 2]];
           bytes[bytes.length - 2] = (byte)((b1 << 2) | (b2 >> 4));
           bytes[bytes.length - 1] = (byte)((b2 << 4) | (b3 >> 2));
       } else {
           b1 = decodingTable[data[data.length - 4]];
           b2 = decodingTable[data[data.length - 3]];
           b3 = decodingTable[data[data.length - 2]];
           b4 = decodingTable[data[data.length - 1]];
           bytes[bytes.length - 3] = (byte)((b1 << 2) | (b2 >> 4));
           bytes[bytes.length - 2] = (byte)((b2 << 4) | (b3 >> 2));
           bytes[bytes.length - 1] = (byte)((b3 << 6) | b4);
       }
       return bytes;
   }
   /**
    * decode the base 64 encoded String data.
    * 
    * TODO: Use the byte version to avoid duplication?
    * 
    * @return a byte array representing the decoded data.
    */
   public static byte[] decode(String data) {
       byte[] bytes;
       byte b1, b2, b3, b4;
       data = discardNonBase64Chars(data);
       if (data.charAt(data.length() - 2) == "=") {
           bytes = new byte[(((data.length() / 4) - 1) * 3) + 1];
       } else if (data.charAt(data.length() - 1) == "=") {
           bytes = new byte[(((data.length() / 4) - 1) * 3) + 2];
       } else {
           bytes = new byte[((data.length() / 4) * 3)];
       }
       for (int i = 0, j = 0; i < data.length() - 4; i += 4, j += 3) {
           b1 = decodingTable[data.charAt(i)];
           b2 = decodingTable[data.charAt(i + 1)];
           b3 = decodingTable[data.charAt(i + 2)];
           b4 = decodingTable[data.charAt(i + 3)];
           bytes[j] = (byte)((b1 << 2) | (b2 >> 4));
           bytes[j + 1] = (byte)((b2 << 4) | (b3 >> 2));
           bytes[j + 2] = (byte)((b3 << 6) | b4);
       }
       if (data.charAt(data.length() - 2) == "=") {
           b1 = decodingTable[data.charAt(data.length() - 4)];
           b2 = decodingTable[data.charAt(data.length() - 3)];
           bytes[bytes.length - 1] = (byte)((b1 << 2) | (b2 >> 4));
       } else if (data.charAt(data.length() - 1) == "=") {
           b1 = decodingTable[data.charAt(data.length() - 4)];
           b2 = decodingTable[data.charAt(data.length() - 3)];
           b3 = decodingTable[data.charAt(data.length() - 2)];
           bytes[bytes.length - 2] = (byte)((b1 << 2) | (b2 >> 4));
           bytes[bytes.length - 1] = (byte)((b2 << 4) | (b3 >> 2));
       } else {
           b1 = decodingTable[data.charAt(data.length() - 4)];
           b2 = decodingTable[data.charAt(data.length() - 3)];
           b3 = decodingTable[data.charAt(data.length() - 2)];
           b4 = decodingTable[data.charAt(data.length() - 1)];
           bytes[bytes.length - 3] = (byte)((b1 << 2) | (b2 >> 4));
           bytes[bytes.length - 2] = (byte)((b2 << 4) | (b3 >> 2));
           bytes[bytes.length - 1] = (byte)((b3 << 6) | b4);
       }
       return bytes;
   }

   /**
    * Decode the string and convert back the decoded value into a string
    * using the specified charset. 
    * Use default encoding if charset is null or invalid.
    */
   public static String decode(String data, String charset) {
       if (charset == null){
           // use default
           return new String(Base64.decode(data));            
       }
       try {
           return new String(Base64.decode(data), charset);
       } catch (UnsupportedEncodingException ex) {
           return new String(Base64.decode(data));
       }
   }
   /**
    * Decode the string and convert back the decoded value into a string
    * using the specified charset. 
    * Use default encoding if charset is null or invalid.
    */
   public static String decode(byte[] data, String charset) {
       if (charset == null){
           // use default
           return new String(Base64.decode(data));            
       }
       try {
           return new String(Base64.decode(data), charset);
       } catch (UnsupportedEncodingException ex) {
           return new String(Base64.decode(data));
       }
   }
   // --------------------------------------------------------- Private Methods
   /**
    * Discards any characters outside of the base64 alphabet (see page 25 of
    * RFC 2045) "Any characters outside of the base64 alphabet are to be
    * ignored in base64 encoded data."
    * 
    * @param data
    *            the base64 encoded data
    * @return the data, less non-base64 characters.
    */
   private static byte[] discardNonBase64Bytes(byte[] data) {
       byte temp[] = new byte[data.length];
       int bytesCopied = 0;
       for (int i = 0; i < data.length; i++) {
           if (isValidBase64Byte(data[i])) {
               temp[bytesCopied++] = data[i];
           }
       }
       byte newData[] = new byte[bytesCopied];
       System.arraycopy(temp, 0, newData, 0, bytesCopied);
       return newData;
   }
   /**
    * Discards any characters outside of the base64 alphabet (see page 25 of
    * RFC 2045) "Any characters outside of the base64 alphabet are to be
    * ignored in base64 encoded data."
    * 
    * @param data
    *            the base64 encoded data
    * @return the data, less non-base64 characters.
    */
   private static String discardNonBase64Chars(String data) {
       StringBuffer sb = new StringBuffer();
       int length = data.length();
       for (int i = 0; i < length; i++) {
           if (isValidBase64Byte((byte)(data.charAt(i)))) {
               sb.append(data.charAt(i));
           }
       }
       return sb.toString();
   }
   /**
    * Checks is the given byte is in base64 alphabet
    * 
    * @param b
    *            the byte to check
    * @return boolean true if the byte is in base64 alphabet
    */
   private static boolean isValidBase64Byte(byte b) {
       if (b == "=") {
           return true;
       } else if (b < 0 || b >= 128) {
           return false;
       } else if (decodingTable[b] == -1) {
           return false;
       }
       return true;
   }

}



 </source>
   
  
 
  



Base64 Utils

   <source lang="java">
   

// Revised act soap util; import java.io.IOException; import java.io.OutputStream; import java.io.Writer; import java.io.ByteArrayOutputStream; public class Base64Utils {

   private static final char[] S_BASE64CHAR = {
     "A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
     "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
     "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d",
     "e", "f", "g", "h", "i", "j", "k", "l", "m", "n",
     "o", "p", "q", "r", "s", "t", "u", "v", "w", "x",
     "y", "z", "0", "1", "2", "3", "4", "5", "6", "7",
     "8", "9", "+", "/"
 };
 private static final char S_BASE64PAD = "=";
   private static final byte[] S_DECODETABLE = new byte[128];
 static {
   for (int i = 0; i < S_DECODETABLE.length; i++) {
     S_DECODETABLE[i] = Byte.MAX_VALUE;     }
   for (int i = 0; i < S_BASE64CHAR.length; i++) {       S_DECODETABLE[S_BASE64CHAR[i]] = (byte) i;
   }
 }
 
 private static int base64Decode0(char[] ibuf, byte[] obuf, int wp) {
   int outlen = 3;
   if (ibuf[3] == S_BASE64PAD) {
     outlen = 2;
   }
   if (ibuf[2] == S_BASE64PAD) {
     outlen = 1;
   }
   int b0 = S_DECODETABLE[ibuf[0]];
   int b1 = S_DECODETABLE[ibuf[1]];
   int b2 = S_DECODETABLE[ibuf[2]];
   int b3 = S_DECODETABLE[ibuf[3]];
   switch (outlen) {
     case 1:
       obuf[wp] = (byte) (b0 << 2 & 0xfc | b1 >> 4 & 0x3);
       return 1;
     case 2:
       obuf[wp++] = (byte) (b0 << 2 & 0xfc | b1 >> 4 & 0x3);
       obuf[wp] = (byte) (b1 << 4 & 0xf0 | b2 >> 2 & 0xf);
       return 2;
     case 3:
       obuf[wp++] = (byte) (b0 << 2 & 0xfc | b1 >> 4 & 0x3);
       obuf[wp++] = (byte) (b1 << 4 & 0xf0 | b2 >> 2 & 0xf);
       obuf[wp] = (byte) (b2 << 6 & 0xc0 | b3 & 0x3f);
       return 3;
     default:
       throw new RuntimeException("Internal Errror");
   }
 }
 
 public static byte[] base64Decode(char[] data, int off, int len) {
   char[] ibuf = new char[4];
   int ibufcount = 0;
   byte[] obuf = new byte[len / 4 * 3 + 3];
   int obufcount = 0;
   for (int i = off; i < off + len; i++) {
     char ch = data[i];
     if (ch == S_BASE64PAD
         || ch < S_DECODETABLE.length && S_DECODETABLE[ch] != Byte.MAX_VALUE) {
       ibuf[ibufcount++] = ch;
       if (ibufcount == ibuf.length) {
         ibufcount = 0;
         obufcount += base64Decode0(ibuf, obuf, obufcount);
       }
     }
   }
   if (obufcount == obuf.length) {
     return obuf;
   }
   byte[] ret = new byte[obufcount];
   System.arraycopy(obuf, 0, ret, 0, obufcount);
   return ret;
 }
 
 public static byte[] base64Decode(String data) {
   char[] ibuf = new char[4];
   int ibufcount = 0;
   byte[] obuf = new byte[data.length() / 4 * 3 + 3];
   int obufcount = 0;
   for (int i = 0; i < data.length(); i++) {
     char ch = data.charAt(i);
     if (ch == S_BASE64PAD
         || ch < S_DECODETABLE.length && S_DECODETABLE[ch] != Byte.MAX_VALUE) {
       ibuf[ibufcount++] = ch;
       if (ibufcount == ibuf.length) {
         ibufcount = 0;
         obufcount += base64Decode0(ibuf, obuf, obufcount);
       }
     }
   }
   if (obufcount == obuf.length) {
     return obuf;
   }
   byte[] ret = new byte[obufcount];
   System.arraycopy(obuf, 0, ret, 0, obufcount);
   return ret;
 }
 
 public static byte[] base64Decode(byte[] data) {
   return base64Decode(data, 0, data.length);
 }
 
 public static byte[] base64Decode(byte[] data, int off, int len) {
   char[] ibuf = new char[4];
   int ibufcount = 0;
   byte[] obuf = new byte[len / 4 * 3 + 3];
   int obufcount = 0;
   for (int i = off; i < off + len; i++) {
     char ch = (char) data[i];
     if (ch == S_BASE64PAD
         || ch < S_DECODETABLE.length && S_DECODETABLE[ch] != Byte.MAX_VALUE) {
       ibuf[ibufcount++] = ch;
       if (ibufcount == ibuf.length) {
         ibufcount = 0;
         obufcount += base64Decode0(ibuf, obuf, obufcount);
       }
     }
   }
   if (obufcount == obuf.length) {
     return obuf;
   }
   byte[] ret = new byte[obufcount];
   System.arraycopy(obuf, 0, ret, 0, obufcount);
   return ret;
 }
 
 public static void base64Decode(char[] data, int off, int len,
                                 OutputStream ostream) throws IOException {
   char[] ibuf = new char[4];
   int ibufcount = 0;
   byte[] obuf = new byte[3];
   for (int i = off; i < off + len; i++) {
     char ch = data[i];
     if (ch == S_BASE64PAD
         || ch < S_DECODETABLE.length && S_DECODETABLE[ch] != Byte.MAX_VALUE) {
       ibuf[ibufcount++] = ch;
       if (ibufcount == ibuf.length) {
         ibufcount = 0;
         int obufcount = base64Decode0(ibuf, obuf, 0);
         ostream.write(obuf, 0, obufcount);
       }
     }
   }
 }
 
 public static void base64Decode(String data, OutputStream ostream) throws
     IOException {
   char[] ibuf = new char[4];
   int ibufcount = 0;
   byte[] obuf = new byte[3];
   for (int i = 0; i < data.length(); i++) {
     char ch = data.charAt(i);
     if (ch == S_BASE64PAD
         || ch < S_DECODETABLE.length && S_DECODETABLE[ch] != Byte.MAX_VALUE) {
       ibuf[ibufcount++] = ch;
       if (ibufcount == ibuf.length) {
         ibufcount = 0;
         int obufcount = base64Decode0(ibuf, obuf, 0);
         ostream.write(obuf, 0, obufcount);
       }
     }
   }
 }
 
 
 public static String base64Encode(byte[] data) {
   return base64Encode(data, 0, data.length);
 }
 
 
 public static String base64Encode(byte[] data, int off, int len) {
   if (len <= 0) {
     return "";
   }
   char[] out = new char[len / 3 * 4 + 4];
   int rindex = off;
   int windex = 0;
   int rest = len;
   while (rest >= 3) {
     int i = ( (data[rindex] & 0xff) << 16)
         + ( (data[rindex + 1] & 0xff) << 8)
         + (data[rindex + 2] & 0xff);
     out[windex++] = S_BASE64CHAR[i >> 18];
     out[windex++] = S_BASE64CHAR[ (i >> 12) & 0x3f];
     out[windex++] = S_BASE64CHAR[ (i >> 6) & 0x3f];
     out[windex++] = S_BASE64CHAR[i & 0x3f];
     rindex += 3;
     rest -= 3;
   }
   if (rest == 1) {
     int i = data[rindex] & 0xff;
     out[windex++] = S_BASE64CHAR[i >> 2];
     out[windex++] = S_BASE64CHAR[ (i << 4) & 0x3f];
     out[windex++] = S_BASE64PAD;
     out[windex++] = S_BASE64PAD;
   }
   else if (rest == 2) {
     int i = ( (data[rindex] & 0xff) << 8) + (data[rindex + 1] & 0xff);
     out[windex++] = S_BASE64CHAR[i >> 10];
     out[windex++] = S_BASE64CHAR[ (i >> 4) & 0x3f];
     out[windex++] = S_BASE64CHAR[ (i << 2) & 0x3f];
     out[windex++] = S_BASE64PAD;
   }
   return new String(out, 0, windex);
 }
 
 
 public static void base64Encode(byte[] data, int off, int len,
                                 OutputStream ostream) throws IOException {
   if (len <= 0) {
     return;
   }
   byte[] out = new byte[4];
   int rindex = off;
   int rest = len - off;
   while (rest >= 3) {
     int i = ( (data[rindex] & 0xff) << 16)
         + ( (data[rindex + 1] & 0xff) << 8)
         + (data[rindex + 2] & 0xff);
     out[0] = (byte) S_BASE64CHAR[i >> 18];
     out[1] = (byte) S_BASE64CHAR[ (i >> 12) & 0x3f];
     out[2] = (byte) S_BASE64CHAR[ (i >> 6) & 0x3f];
     out[3] = (byte) S_BASE64CHAR[i & 0x3f];
     ostream.write(out, 0, 4);
     rindex += 3;
     rest -= 3;
   }
   if (rest == 1) {
     int i = data[rindex] & 0xff;
     out[0] = (byte) S_BASE64CHAR[i >> 2];
     out[1] = (byte) S_BASE64CHAR[ (i << 4) & 0x3f];
     out[2] = (byte) S_BASE64PAD;
     out[3] = (byte) S_BASE64PAD;
     ostream.write(out, 0, 4);
   }
   else if (rest == 2) {
     int i = ( (data[rindex] & 0xff) << 8) + (data[rindex + 1] & 0xff);
     out[0] = (byte) S_BASE64CHAR[i >> 10];
     out[1] = (byte) S_BASE64CHAR[ (i >> 4) & 0x3f];
     out[2] = (byte) S_BASE64CHAR[ (i << 2) & 0x3f];
     out[3] = (byte) S_BASE64PAD;
     ostream.write(out, 0, 4);
   }
 }
 
 
 public static void base64Encode(byte[] data, int off, int len, Writer writer) throws
     IOException {
   if (len <= 0) {
     return;
   }
   char[] out = new char[4];
   int rindex = off;
   int rest = len - off;
   int output = 0;
   while (rest >= 3) {
     int i = ( (data[rindex] & 0xff) << 16)
         + ( (data[rindex + 1] & 0xff) << 8)
         + (data[rindex + 2] & 0xff);
     out[0] = S_BASE64CHAR[i >> 18];
     out[1] = S_BASE64CHAR[ (i >> 12) & 0x3f];
     out[2] = S_BASE64CHAR[ (i >> 6) & 0x3f];
     out[3] = S_BASE64CHAR[i & 0x3f];
     writer.write(out, 0, 4);
     rindex += 3;
     rest -= 3;
     output += 4;
     if (output % 76 == 0) {
       writer.write("\n");
     }
   }
   if (rest == 1) {
     int i = data[rindex] & 0xff;
     out[0] = S_BASE64CHAR[i >> 2];
     out[1] = S_BASE64CHAR[ (i << 4) & 0x3f];
     out[2] = S_BASE64PAD;
     out[3] = S_BASE64PAD;
     writer.write(out, 0, 4);
   }
   else if (rest == 2) {
     int i = ( (data[rindex] & 0xff) << 8) + (data[rindex + 1] & 0xff);
     out[0] = S_BASE64CHAR[i >> 10];
     out[1] = S_BASE64CHAR[ (i >> 4) & 0x3f];
     out[2] = S_BASE64CHAR[ (i << 2) & 0x3f];
     out[3] = S_BASE64PAD;
     writer.write(out, 0, 4);
   }
 }

}



 </source>
   
  
 
  



byte to be tested if it is Base64 alphabet

   <source lang="java">
   

/* Copyright 2004 The Apache Software Foundation

*
*   Licensed under the Apache License, Version 2.0 (the "License");
*   you may not use this file except in compliance with the License.
*   You may obtain a copy of the License at
*
*       http://www.apache.org/licenses/LICENSE-2.0
*
*   Unless required by applicable law or agreed to in writing, software
*   distributed under the License is distributed on an "AS IS" BASIS,
*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*   See the License for the specific language governing permissions and
*  limitations under the License.
*/

//xmlbeans import java.io.UnsupportedEncodingException; /**

* format validation
*
* This class encodes/decodes hexadecimal data
* @author Jeffrey Rodriguez
* @version $Id: HexBin.java 125124 2005-01-14 00:23:54Z kkrouse $
*/

public class Main {

 static private final int  BASELENGTH   = 255;
 static private final int  LOOKUPLENGTH = 16;
 static private byte [] hexNumberTable    = new byte[BASELENGTH];
 static private byte [] lookUpHexAlphabet = new byte[LOOKUPLENGTH];
 static {
     for (int i = 0; i<BASELENGTH; i++ ) {
         hexNumberTable[i] = -1;
     }
     for ( int i = "9"; i >= "0"; i--) {
         hexNumberTable[i] = (byte) (i-"0");
     }
     for ( int i = "F"; i>= "A"; i--) {
         hexNumberTable[i] = (byte) ( i-"A" + 10 );
     }
     for ( int i = "f"; i>= "a"; i--) {
        hexNumberTable[i] = (byte) ( i-"a" + 10 );
     }
     for(int i = 0; i<10; i++ )
         lookUpHexAlphabet[i] = (byte) ("0"+i );
     for(int i = 10; i<=15; i++ )
         lookUpHexAlphabet[i] = (byte) ("A"+i -10);
 }
 /**
  * byte to be tested if it is Base64 alphabet
  *
  * @param octect
  * @return
  */
 static boolean isHex(byte octect) {
     return (hexNumberTable[octect] != -1);
 }

}



 </source>
   
  
 
  



Codes number up to radix 62

   <source lang="java">
   

/*

* Copyright 2000,2005 wingS development team.
*
* This file is part of wingS (http://wingsframework.org).
*
* wingS is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* Please see COPYING for the complete licence.
*/

import java.util.StringTokenizer; /**

* Some string manipulation utilities.
*
* @author 
*/

public class StringUtil {

 private final static char[] ALPHAS = {
     "a", "b",
     "c", "d", "e", "f", "g", "h",
     "i", "j", "k", "l", "m", "n",
     "o", "p", "q", "r", "s", "t",
     "u", "v", "w", "x", "y", "z",
 };
 /**
  * All possible digits for representing a number as a String
  * This is conservative and does not include "special"
  * characters since some browsers don"t handle them right.
  * The IE for instance seems to be case insensitive in class
  * names for CSSs. Grrr.
  */
 private final static char[] DIGITS = {
     "0", "1", "2", "3", "4", "5",
     "6", "7", "8", "9", "a", "b",
     "c", "d", "e", "f", "g", "h",
     "i", "j", "k", "l", "m", "n",
     "o", "p", "q", "r", "s", "t",
     "u", "v", "w", "x", "y", "z",
     /* This %@&!-IE is case insensitive for certain
      * URLs and IDs
      * "A" , "B" ,
      * "C" , "D" , "E" , "F" , "G" , "H" ,
      * "I" , "J" , "K" , "L" , "M" , "N" ,
      * "O" , "P" , "Q" , "R" , "S" , "T" ,
      * "U" , "V" , "W" , "X" , "Y" , "Z"
      */
 };
 public static final int MAX_RADIX = DIGITS.length;
 /**
  * Codes number up to radix 62.
  * Note, this method is only public for backward compatiblity. don"t
  * use it.
  *
  * @param minDigits returns a string with a least minDigits digits
  */
 public static String toString(long i, int radix, int minDigits) {
     char[] buf = new char[65];
     radix = Math.min(Math.abs(radix), MAX_RADIX);
     minDigits = Math.min(buf.length - 1, Math.abs(minDigits));
     int charPos = buf.length - 1;
     boolean negative = (i < 0);
     if (negative) {
         i = -i;
     }
     while (i >= radix) {
         buf[charPos--] = DIGITS[(int) (i % radix)];
         i /= radix;
     }
     buf[charPos] = DIGITS[(int) i];
     // if minimum length of the result string is set, pad it with the
     // zero-representation (that is: "0")
     while (charPos > buf.length - minDigits)
         buf[--charPos] = DIGITS[0];
     if (negative) {
         buf[--charPos] = "-";
     }
     return new String(buf, charPos, buf.length - charPos);
 }
 

}



 </source>
   
  
 
  



Converting hexadecimal strings

   <source lang="java">
   

/*

* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id$ */

/**

* Provides helper functions for converting hexadecimal strings.
*/

public class HexUtil {

   private static final char[] DIGITS = 
       {"0", "1", "2", "3", "4", "5", "6", "7",
        "8", "9", "A", "B", "C", "D", "E", "F"};
   /**
    * Converts a byte array to a hexadecimal String
    * @param data the data to encode
    * @return String the resulting String
    */
   public static final String toHex(byte[] data) {
       final StringBuffer sb = new StringBuffer(data.length * 2);
       for (int i = 0; i < data.length; i++) {
           sb.append(DIGITS[(data[i] >>> 4) & 0x0F]);
           sb.append(DIGITS[data[i] & 0x0F]);
       }
       return sb.toString();
   }
   

}



 </source>
   
  
 
  



Convert to hex from byte arrays and back

   <source lang="java">
   

/**

* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**

* Used to convert to hex from byte arrays and back.
* 
* @version $Revision: 1.2 $
*/

public final class HexSupport {

   private static final String[] HEX_TABLE = new String[]{
       "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f",
       "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f",
       "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f",
       "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f",
       "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c", "4d", "4e", "4f",
       "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e", "5f",
       "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d", "6e", "6f",
       "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d", "7e", "7f",
       "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f",
       "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f",
       "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af",
       "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf",
       "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf",
       "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "da", "db", "dc", "dd", "de", "df",
       "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef",
       "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff",
   };
   private static final int[] INT_OFFSETS = new int[]{
     24,16,8,0
   };
   
   private HexSupport() {
   }
   
   /**
    * @param hex
    * @return
    */
   public static byte[] toBytesFromHex(String hex) {
       byte rc[] = new byte[hex.length() / 2];
       for (int i = 0; i < rc.length; i++) {
           String h = hex.substring(i * 2, i * 2 + 2);
           int x = Integer.parseInt(h, 16);
           rc[i] = (byte) x;
       }
       return rc;
   }
   /**
    * @param bytes
    * @return
    */
   public static String toHexFromBytes(byte[] bytes) {
       StringBuffer rc = new StringBuffer(bytes.length * 2);
       for (int i = 0; i < bytes.length; i++) {
           rc.append(HEX_TABLE[0xFF & bytes[i]]);
       }
       return rc.toString();
   }
   /**
    * 
    * @param value 
    * @param trim if the leading 0"s should be trimmed off.
    * @return
    */
   public static String toHexFromInt(int value, boolean trim) {
       StringBuffer rc = new StringBuffer(INT_OFFSETS.length*2);
       for (int i = 0; i < INT_OFFSETS.length; i++) {
         int b = 0xFF & (value>>INT_OFFSETS[i]);
         if( !(trim && b == 0) ) { 
           rc.append(HEX_TABLE[b]);
           trim=false;
         }
       }
       return rc.toString();
   }

}



 </source>
   
  
 
  



Decodes Base64 data into octects

   <source lang="java">
   

/* Copyright 2004 The Apache Software Foundation

*
*   Licensed under the Apache License, Version 2.0 (the "License");
*   you may not use this file except in compliance with the License.
*   You may obtain a copy of the License at
*
*       http://www.apache.org/licenses/LICENSE-2.0
*
*   Unless required by applicable law or agreed to in writing, software
*   distributed under the License is distributed on an "AS IS" BASIS,
*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*   See the License for the specific language governing permissions and
*  limitations under the License.
*/

import java.io.UnsupportedEncodingException; /**

* This class provides encode/decode for RFC 2045 Base64 as
* defined by RFC 2045, N. Freed and N. Borenstein.
* RFC 2045: Multipurpose Internet Mail Extensions (MIME)
* Part One: Format of Internet Message Bodies. Reference
* 1996 Available at: http://www.ietf.org/rfc/rfc2045.txt
* This class is used by XML Schema binary format validation
*
* This implementation does not encode/decode streaming
* data. You need the data that you will encode/decode
* already on a byte arrray.
* 
* 
* From xmlbeans
* @author Jeffrey Rodriguez
* @author Sandy Gao
* @version $Id: Base64.java 111285 2004-12-08 16:54:26Z cezar $
*/

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 byte PAD                = ( byte ) "=";
   static private final boolean fDebug          = false;
   static private byte [] base64Alphabet        = new byte[BASELENGTH];
   static private byte [] lookUpBase64Alphabet  = new byte[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<=25; i++)
           lookUpBase64Alphabet[i] = (byte) ("A"+i );
       for (int i = 26,  j = 0; i<=51; i++, j++)
           lookUpBase64Alphabet[i] = (byte) ("a"+ j );
       for (int i = 52,  j = 0; i<=61; i++, j++)
           lookUpBase64Alphabet[i] = (byte) ("0" + j );
       lookUpBase64Alphabet[62] = (byte) "+";
       lookUpBase64Alphabet[63] = (byte) "/";
   }
   protected static boolean isWhiteSpace(byte octect) {
       return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9);
   }
   protected static boolean isPad(byte octect) {
       return (octect == PAD);
   }
   protected static boolean isData(byte octect) {
       return (base64Alphabet[octect] != -1);
   }
   protected static boolean isBase64(byte octect) {
       return (isWhiteSpace(octect) || isPad(octect) || isData(octect));
   }
   /**
    * Encodes hex octects into Base64
    *
    * @param binaryData Array containing binaryData
    * @return Encoded Base64 array
    */
   public static byte[] encode(byte[] binaryData) {
       if (binaryData == null)
           return null;
       int      lengthDataBits    = binaryData.length*EIGHTBIT;
       int      fewerThan24bits   = lengthDataBits%TWENTYFOURBITGROUP;
       int      numberTriplets    = lengthDataBits/TWENTYFOURBITGROUP;
       byte     encodedData[]     = null;
       if (fewerThan24bits != 0) //data not divisible by 24 bit
           encodedData = new byte[ (numberTriplets + 1 )*4  ];
       else // 16 or 8 bit
           encodedData = new byte[ numberTriplets*4 ];
       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 (i = 0; i<numberTriplets; i++) {
           dataIndex = i*3;
           b1 = binaryData[dataIndex];
           b2 = binaryData[dataIndex + 1];
           b3 = binaryData[dataIndex + 2];
           if (fDebug) {
               System.out.println( "b1= " + b1 +", b2= " + b2 + ", b3= " + b3 );
           }
           l  = (byte)(b2 & 0x0f);
           k  = (byte)(b1 & 0x03);
           encodedIndex = i*4;
           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);
           encodedData[encodedIndex]   = lookUpBase64Alphabet[ val1 ];
           if (fDebug) {
               System.out.println( "val2 = " + val2 );
               System.out.println( "k4   = " + (k<<4));
               System.out.println( "vak  = " + (val2 | (k<<4)));
           }
           encodedData[encodedIndex+1] = lookUpBase64Alphabet[ val2 | ( k<<4 )];
           encodedData[encodedIndex+2] = lookUpBase64Alphabet[ (l <<2 ) | val3 ];
           encodedData[encodedIndex+3] = lookUpBase64Alphabet[ b3 & 0x3f ];
       }
       // form integral number of 6-bit groups
       dataIndex    = i*3;
       encodedIndex = i*4;
       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 + 1] = lookUpBase64Alphabet[ k<<4 ];
           encodedData[encodedIndex + 2] = PAD;
           encodedData[encodedIndex + 3] = 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 + 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 containind decoded data.
    */
   public static byte[] decode(byte[] base64Data) {
       if (base64Data == null)
           return null;
       // remove white spaces
       base64Data = removeWhiteSpace(base64Data);
       if (base64Data.length%FOURBYTE != 0) {
           return null;//should be divisible by four
       }
       int      numberQuadruple    = (base64Data.length/FOURBYTE );
       if (numberQuadruple == 0)
           return new byte[0];
       byte     decodedData[]      = null;
       byte     b1=0,b2=0,b3=0, b4=0;//, marker0=0, marker1=0;
       byte     d1=0,d2=0,d3=0,d4=0;
       // Throw away anything not in normalizedBase64Data
       // Adjust size
       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[dataIndex++]) )||
               !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 PAD e.g. 3c[Pad][Pad]
               if ((b2 & 0xf) != 0)//last 4 bits should be 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 be 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;//an 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;
   }

// /** // * Decodes Base64 data into octects // * // * @param base64Data String containing Base64 data // * @return string containing decoded data. // */ // public static String decode(String base64Data) { // if (base64Data == null) // return null; // // byte[] decoded = null; // try { // decoded = decode(base64Data.getBytes("utf-8")); // } // catch(UnsupportedEncodingException e) { // } // finally { // return decoded == null ? null : new String(decoded); // } // } // // /** // * Encodes octects (using utf-8) into Base64 data // * // * @param binaryData String containing Hex data // * @return string containing decoded data. // */ // public static String encode(String binaryData) { // if (binaryData == null) // return null; // // byte[] encoded = null; // try { // encoded = encode(binaryData.getBytes("utf-8")); // } // catch(UnsupportedEncodingException e) {} // finally { // return encoded == null ? null : new String(encoded); // } // }

   /**
    * remove WhiteSpace from MIME containing encoded Base64 data.
    *
    * @param data  the byte array of base64 data (with WS)
    * @return      the byte array of base64 data (without WS)
    */
   protected static byte[] removeWhiteSpace(byte[] data) {
       if (data == null)
           return null;
       // count characters that"s not whitespace
       int newSize = 0;
       int len = data.length;
       for (int i = 0; i < len; i++) {
           if (!isWhiteSpace(data[i]))
               newSize++;
       }
       // if no whitespace, just return the input array
       if (newSize == len)
           return data;
       // create the array to return
       byte[] newArray = new byte[newSize];
       int j = 0;
       for (int i = 0; i < len; i++) {
           if (!isWhiteSpace(data[i]))
               newArray[j++] = data[i];
       }
       return newArray;
   }

}



 </source>
   
  
 
  



Encode and decode data in Base64 format as described in RFC 1521

   <source lang="java">
   

/**************************************************************************

*
* A Base64 Encoder/Decoder.
*
* This class is used to encode and decode data in Base64 format
* as described in RFC 1521.
*
*

* Copyright 2003: Christian d"Heureuse, Inventec Informatik AG, Switzerland.
* License: This is "Open Source" software and released under the
* * <p> * Version history:
* 2003-07-22 Christian d"Heureuse (chdh): Module created.
* 2005-08-11 chdh: Lincense changed from GPL to LGPL. * **************************************************************************/ public class Base64Coder { // Mapping table from 6-bit nibbles to Base64 characters. private static char[] map1 = new char[64]; static { int i = 0; for (char c = "A"; c <= "Z"; c++) map1[i++] = c; for (char c = "a"; c <= "z"; c++) map1[i++] = c; for (char c = "0"; c <= "9"; c++) map1[i++] = c; map1[i++] = "+"; map1[i++] = "/"; } // Mapping table from Base64 characters to 6-bit nibbles. private static byte[] map2 = new byte[128]; static { for (int i = 0; i < map2.length; i++) map2[i] = -1; for (int i = 0; i < 64; i++) map2[map1[i]] = (byte) i; } /** * Encodes a string into Base64 format. * No blanks or line breaks are inserted. * @param s a String to be encoded. * @return A String with the Base64 encoded data. */ public static String encode(String s) { return new String(encode(s.getBytes())); } /** * Encodes a byte array into Base64 format. * No blanks or line breaks are inserted. * @param in an array containing the data bytes to be encoded. * @return A character array with the Base64 encoded data. */ public static char[] encode(byte[] in) { int iLen = in.length; int oDataLen = (iLen * 4 + 2) / 3; // output length without padding int oLen = ((iLen + 2) / 3) * 4; // output length including padding char[] out = new char[oLen]; int ip = 0; int op = 0; while (ip < iLen) { int i0 = in[ip++] & 0xff; int i1 = ip < iLen ? in[ip++] & 0xff : 0; int i2 = ip < iLen ? in[ip++] & 0xff : 0; int o0 = i0 >>> 2; int o1 = ((i0 & 3) << 4) | (i1 >>> 4); int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6); int o3 = i2 & 0x3F; out[op++] = map1[o0]; out[op++] = map1[o1]; out[op] = op < oDataLen ? map1[o2] : "="; op++; out[op] = op < oDataLen ? map1[o3] : "="; op++; } return out; } /** * Decodes a Base64 string. * @param s a Base64 String to be decoded. * @return A String containing the decoded data. * @throws IllegalArgumentException if the input is not valid Base64 encoded data. */ public static String decode(String s) { return new String(decode(s.toCharArray())); } /** * Decodes Base64 data. * No blanks or line breaks are allowed within the Base64 encoded data. * @param in a character array containing the Base64 encoded data. * @return An array containing the decoded data bytes. * @throws IllegalArgumentException if the input is not valid Base64 encoded data. */ public static byte[] decode(char[] in) { int iLen = in.length; if (iLen % 4 != 0) throw new IllegalArgumentException( "Length of Base64 encoded input string is not a multiple of 4."); while (iLen > 0 && in[iLen - 1] == "=") iLen--; int oLen = (iLen * 3) / 4; byte[] out = new byte[oLen]; int ip = 0; int op = 0; while (ip < iLen) { int i0 = in[ip++]; int i1 = in[ip++]; int i2 = ip < iLen ? in[ip++] : "A"; int i3 = ip < iLen ? in[ip++] : "A"; if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127) throw new IllegalArgumentException( "Illegal character in Base64 encoded data."); int b0 = map2[i0]; int b1 = map2[i1]; int b2 = map2[i2]; int b3 = map2[i3]; if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0) throw new IllegalArgumentException( "Illegal character in Base64 encoded data."); int o0 = (b0 << 2) | (b1 >>> 4); int o1 = ((b1 & 0xf) << 4) | (b2 >>> 2); int o2 = ((b2 & 3) << 6) | b3; out[op++] = (byte) o0; if (op < oLen) out[op++] = (byte) o1; if (op < oLen) out[op++] = (byte) o2; } return out; } } </source>

Encode and decode integers, times, and internationalized strings to and from popular binary formats

   <source lang="java">
   

/* encdec - encode and decode integers, times, and

* internationalized strings to and from popular binary formats
* http://www.ioplex.ru/~miallen/encdec/
* Copyright (c) 2003 Michael B. Allen <mballen@erols.ru>
*
* The GNU Library General Public License
* 
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
* 
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Library General Public License for more details.
* 
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA
*/

import java.util.Date; import java.io.IOException; public class Encdec {

   public static final long MILLISECONDS_BETWEEN_1970_AND_1601 = 11644473600000L;
   public static final long SEC_BETWEEEN_1904_AND_1970 = 2082844800L;
   public static final int TIME_1970_SEC_32BE = 1;
   public static final int TIME_1970_SEC_32LE = 2;
   public static final int TIME_1904_SEC_32BE = 3;
   public static final int TIME_1904_SEC_32LE = 4;
   public static final int TIME_1601_NANOS_64LE = 5;
   public static final int TIME_1601_NANOS_64BE = 6;
   public static final int TIME_1970_MILLIS_64BE = 7;
   public static final int TIME_1970_MILLIS_64LE = 8;
   /* Encode integers
    */
   public static int enc_uint16be( short s, byte[] dst, int di ) {
       dst[di++] = (byte)((s >> 8) & 0xFF);
       dst[di] = (byte)(s & 0xFF);
       return 2;
   }
   public static int enc_uint32be( int i, byte[] dst, int di ) {
       dst[di++] = (byte)((i >> 24) & 0xFF);
       dst[di++] = (byte)((i >> 16) & 0xFF);
       dst[di++] = (byte)((i >> 8) & 0xFF);
       dst[di] = (byte)(i & 0xFF);
       return 4;
   }
   public static int enc_uint16le( short s, byte[] dst, int di )
   {
       dst[di++] = (byte)(s & 0xFF);
       dst[di] = (byte)((s >> 8) & 0xFF);
       return 2;
   }
   public static int enc_uint32le( int i, byte[] dst, int di )
   {
       dst[di++] = (byte)(i & 0xFF);
       dst[di++] = (byte)((i >> 8) & 0xFF);
       dst[di++] = (byte)((i >> 16) & 0xFF);
       dst[di] = (byte)((i >> 24) & 0xFF);
       return 4;
   }
   /* Decode integers
    */
   public static short dec_uint16be( byte[] src, int si )
   {
       return (short)(((src[si] & 0xFF) << 8) | (src[si + 1] & 0xFF));
   }
   public static int dec_uint32be( byte[] src, int si )
   {
       return ((src[si] & 0xFF) << 24) | ((src[si + 1] & 0xFF) << 16) |
              ((src[si + 2] & 0xFF) << 8) | (src[si + 3] & 0xFF);
   }
   public static short dec_uint16le( byte[] src, int si )
   {
       return (short)((src[si] & 0xFF) | ((src[si + 1] & 0xFF) << 8));
   }
   public static int dec_uint32le( byte[] src, int si )
   {
       return (src[si] & 0xFF) | ((src[si + 1] & 0xFF) << 8) |
              ((src[si + 2] & 0xFF) << 16) | ((src[si + 3] & 0xFF) << 24);
   }
   /* Encode and decode 64 bit integers
    */
   public static int enc_uint64be( long l, byte[] dst, int di )
   {
       enc_uint32be( (int)(l & 0xFFFFFFFFL), dst, di + 4 );
       enc_uint32be( (int)(( l >> 32L ) & 0xFFFFFFFFL), dst, di );
       return 8;
   }
   public static int enc_uint64le( long l, byte[] dst, int di )
   {
       enc_uint32le( (int)(l & 0xFFFFFFFFL), dst, di );
       enc_uint32le( (int)(( l >> 32L ) & 0xFFFFFFFFL), dst, di + 4 );
       return 8;
   }
   public static long dec_uint64be( byte[] src, int si )
   {
       long l;
       l = dec_uint32be( src, si ) & 0xFFFFFFFFL;
       l <<= 32L;
       l |= dec_uint32be( src, si + 4 ) & 0xFFFFFFFFL;
       return l;
   }
   public static long dec_uint64le( byte[] src, int si )
   {
       long l;
       l = dec_uint32le( src, si + 4 ) & 0xFFFFFFFFL;
       l <<= 32L;
       l |= dec_uint32le( src, si ) & 0xFFFFFFFFL;
       return l;
   }
   /* Encode floats
    */
   public static int enc_floatle( float f, byte[] dst, int di )
   {
       return enc_uint32le( Float.floatToIntBits( f ), dst, di );
   }
   public static int enc_floatbe( float f, byte[] dst, int di )
   {
       return enc_uint32be( Float.floatToIntBits( f ), dst, di );
   }
   /* Decode floating point numbers
    */
   public static float dec_floatle( byte[] src, int si )
   {
       return Float.intBitsToFloat( dec_uint32le( src, si ));
   }
   public static float dec_floatbe( byte[] src, int si )
   {
       return Float.intBitsToFloat( dec_uint32be( src, si ));
   }
   /* Encode and decode doubles
    */
   public static int enc_doublele( double d, byte[] dst, int di )
   {
       return enc_uint64le( Double.doubleToLongBits( d ), dst, di );
   }
   public static int enc_doublebe( double d, byte[] dst, int di )
   {
       return enc_uint64be( Double.doubleToLongBits( d ), dst, di );
   }
   public static double dec_doublele( byte[] src, int si )
   {
       return Double.longBitsToDouble( dec_uint64le( src, si ));
   }
   public static double dec_doublebe( byte[] src, int si )
   {
       return Double.longBitsToDouble( dec_uint64be( src, si ));
   }
   /* Encode times
    */
   public static int enc_time( Date date, byte[] dst, int di, int enc )
   {
       long t;
       switch( enc ) {
           case TIME_1970_SEC_32BE:
               return enc_uint32be( (int)(date.getTime() / 1000L), dst, di );
           case TIME_1970_SEC_32LE:
               return enc_uint32le( (int)(date.getTime() / 1000L), dst, di );
           case TIME_1904_SEC_32BE:
               return enc_uint32be( (int)((date.getTime() / 1000L +
                   SEC_BETWEEEN_1904_AND_1970) & 0xFFFFFFFF), dst, di );
           case TIME_1904_SEC_32LE:
               return enc_uint32le( (int)((date.getTime() / 1000L +
                   SEC_BETWEEEN_1904_AND_1970) & 0xFFFFFFFF), dst, di );
           case TIME_1601_NANOS_64BE:
               t = (date.getTime() + MILLISECONDS_BETWEEN_1970_AND_1601) * 10000L;
               return enc_uint64be( t, dst, di );
           case TIME_1601_NANOS_64LE:
               t = (date.getTime() + MILLISECONDS_BETWEEN_1970_AND_1601) * 10000L;
               return enc_uint64le( t, dst, di );
           case TIME_1970_MILLIS_64BE:
               return enc_uint64be( date.getTime(), dst, di );
           case TIME_1970_MILLIS_64LE:
               return enc_uint64le( date.getTime(), dst, di );
           default:
               throw new IllegalArgumentException( "Unsupported time encoding" );
       }
   }
   /* Decode times
    */
   public static Date dec_time( byte[] src, int si, int enc )
   {
       long t;
   
       switch( enc ) {
           case TIME_1970_SEC_32BE:
               return new Date( dec_uint32be( src, si ) * 1000L );
           case TIME_1970_SEC_32LE:
               return new Date( dec_uint32le( src, si ) * 1000L );
           case TIME_1904_SEC_32BE:
               return new Date((( dec_uint32be( src, si ) & 0xFFFFFFFFL) -
                   SEC_BETWEEEN_1904_AND_1970 ) * 1000L );
           case TIME_1904_SEC_32LE:
               return new Date((( dec_uint32le( src, si ) & 0xFFFFFFFFL) -
                   SEC_BETWEEEN_1904_AND_1970 ) * 1000L );
           case TIME_1601_NANOS_64BE:
               t = dec_uint64be( src, si );
               return new Date( t / 10000L - MILLISECONDS_BETWEEN_1970_AND_1601);
           case TIME_1601_NANOS_64LE:
               t = dec_uint64le( src, si );
               return new Date( t / 10000L - MILLISECONDS_BETWEEN_1970_AND_1601);
           case TIME_1970_MILLIS_64BE:
               return new Date( dec_uint64be( src, si ));
           case TIME_1970_MILLIS_64LE:
               return new Date( dec_uint64le( src, si ));
           default:
               throw new IllegalArgumentException( "Unsupported time encoding" );
       }
   }
   public static int enc_utf8( String str, byte[] dst, int di, int dlim ) throws IOException {
       int start = di, ch;
       int strlen = str.length();
       for( int i = 0; di < dlim && i < strlen; i++ ) {
           ch = str.charAt( i );
           if ((ch >= 0x0001) && (ch <= 0x007F)) {
               dst[di++] = (byte)ch;
           } else if (ch > 0x07FF) {
               if((dlim - di) < 3 ) {
                   break;
               }
               dst[di++] = (byte)(0xE0 | ((ch >> 12) & 0x0F)); 
               dst[di++] = (byte)(0x80 | ((ch >>  6) & 0x3F)); 
               dst[di++] = (byte)(0x80 | ((ch >>  0) & 0x3F)); 
           } else {
               if((dlim - di) < 2 ) {
                   break;
               }
               dst[di++] = (byte)(0xC0 | ((ch >>  6) & 0x1F)); 
               dst[di++] = (byte)(0x80 | ((ch >>  0) & 0x3F)); 
           }
       }
       return di - start;
   }
   public static String dec_utf8( byte[] src, int si, int slim ) throws IOException {
       char[] uni = new char[slim - si];
       int ui, ch;
       for( ui = 0; si < slim && (ch = src[si++] & 0xFF) != 0; ui++ ) {
           if( ch < 0x80 ) {
               uni[ui] = (char)ch;
           } else if((ch & 0xE0) == 0xC0 ) {
               if((slim - si) < 2 ) {
                   break;
               }
               uni[ui] = (char)((ch & 0x1F) << 6);
               ch = src[si++] & 0xFF;
               uni[ui] |= ch & 0x3F;
               if ((ch & 0xC0) != 0x80 || uni[ui] < 0x80 ) {
                   throw new IOException( "Invalid UTF-8 sequence" );
               }
           } else if((ch & 0xF0) == 0xE0 ) {
               if((slim - si) < 3 ) {
                   break;
               }
               uni[ui]  = (char)((ch & 0x0F) << 12);
               ch = src[si++] & 0xFF;
               if ((ch & 0xC0) != 0x80 ) {
                   throw new IOException( "Invalid UTF-8 sequence" );
               } else {
                   uni[ui] |= (ch & 0x3F) << 6;
                   ch = src[si++] & 0xFF;
                   uni[ui] |=  ch & 0x3F;
                   if ((ch & 0xC0) != 0x80 || uni[ui] < 0x800) {
                       throw new IOException( "Invalid UTF-8 sequence" );
                   }
               }
           } else {
               throw new IOException( "Unsupported UTF-8 sequence" );
           }
       }
       return new String( uni, 0, ui );
   }
   public static String dec_ucs2le( byte[] src, int si, int slim, char[] buf ) throws IOException {
       int bi;
       for( bi = 0; (si + 1) < slim; bi++, si += 2 ) {
           buf[bi] = (char)dec_uint16le( src, si );
           if( buf[bi] == "\0" ) {
               break;
           }
       }
       return new String( buf, 0, bi );
   }

}



 </source>
   
  
 
  



Encode/decode for RFC 2045 Base64 as defined by RFC 2045

   <source lang="java">
   

/*

* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
* 
*      http://www.apache.org/licenses/LICENSE-2.0
* 
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**

* This class provides encode/decode for RFC 2045 Base64 as defined by
* RFC 2045, N. Freed and N. Borenstein.  :
* Multipurpose Internet Mail Extensions (MIME) Part One: Format of
* Internet Message Bodies. Reference 1996
*
* @author Jeffrey Rodriguez
* @version $Id: Base64.java 515 2008-03-17 21:02:23Z jfrederic.clere@jboss.ru $
*/

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 byte PAD                = (byte) "=";
   static private byte [] base64Alphabet       = new byte[BASELENGTH];
   static private byte [] lookUpBase64Alphabet = new byte[LOOKUPLENGTH];
   //static private final Log log = LogSource.getInstance("org.apache.rumons.util.Base64");
   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 <= 25; i++ )
           lookUpBase64Alphabet[i] = (byte) ("A" + i);
       for (int i = 26,  j = 0; i <= 51; i++, j++ )
           lookUpBase64Alphabet[i] = (byte) ("a"+ j);
       for (int i = 52,  j = 0; i <= 61; i++, j++ )
           lookUpBase64Alphabet[i] = (byte) ("0" + j);
       lookUpBase64Alphabet[62] = (byte) "+";
       lookUpBase64Alphabet[63] = (byte) "/";
   }
   public static boolean isBase64( String isValidString )
   {
       return isArrayByteBase64(isValidString.getBytes());
   }
   public static boolean isBase64( byte octect )
   {
       //shall we ignore white space? JEFF??
       return (octect == PAD || base64Alphabet[octect] != -1);
   }
   public static boolean isArrayByteBase64( byte[] arrayOctect )
   {
       int length = arrayOctect.length;
       if (length == 0)
       {
           // shouldn"t a 0 length array be valid base64 data?
           // return false;
           return true;
       }
       for (int i=0; i < length; i++)
       {
           if ( !Base64.isBase64(arrayOctect[i]) )
               return false;
       }
       return true;
   }
   /**
    * Encodes hex octects into Base64.
    *
    * @param binaryData Array containing binary data to encode.
    * @return Base64-encoded data.
    */
   public static byte[] encode( byte[] binaryData )
   {
       int      lengthDataBits    = binaryData.length*EIGHTBIT;
       int      fewerThan24bits   = lengthDataBits%TWENTYFOURBITGROUP;
       int      numberTriplets    = lengthDataBits/TWENTYFOURBITGROUP;
       byte     encodedData[]     = null;
       if (fewerThan24bits != 0)
       {
           //data not divisible by 24 bit
           encodedData = new byte[ (numberTriplets + 1 ) * 4 ];
       }
       else
       {
           // 16 or 8 bit
           encodedData = new byte[ numberTriplets * 4 ];
       }
       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);
           k  = (byte)(b1 & 0x03);
           encodedIndex = i * 4;
           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);
           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 ];
       }
       // form integral number of 6-bit groups
       dataIndex    = i*3;
       encodedIndex = i*4;
       if (fewerThan24bits == EIGHTBIT )
       {
           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 == 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 + 1] =
               lookUpBase64Alphabet[ val2 | ( k<<4 )];
           encodedData[encodedIndex + 2] = lookUpBase64Alphabet[ l<<2 ];
           encodedData[encodedIndex + 3] = PAD;
       }
       return encodedData;
   }

}



 </source>
   
  
 
  



Encode/decode for RFC 2045 Base64 as defined by RFC 2045, N. Freed and N. Borenstein.

   <source lang="java">
   

/*

* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
* 
*      http://www.apache.org/licenses/LICENSE-2.0
* 
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**

* This class provides encode/decode for RFC 2045 Base64 as
* defined by RFC 2045, N. Freed and N. Borenstein.
* RFC 2045: Multipurpose Internet Mail Extensions (MIME)
* Part One: Format of Internet Message Bodies. Reference
* 1996 Available at: http://www.ietf.org/rfc/rfc2045.txt
* This class is used by XML Schema binary format validation
*
* This implementation does not encode/decode streaming
* data. You need the data that you will encode/decode
* already on a byte arrray.
*
* @xerces.internal 
*
* @author Jeffrey Rodriguez
* @author Sandy Gao
* @version $Id: Base64.java 446747 2006-09-15 21:46:20Z mrglavas $
*/

public final class Base64 {

   static private final int  BASELENGTH         = 128;
   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<=25; i++)
           lookUpBase64Alphabet[i] = (char)("A"+i);
       for (int i = 26,  j = 0; i<=51; i++, j++)
           lookUpBase64Alphabet[i] = (char)("a"+ j);
       for (int i = 52,  j = 0; i<=61; 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 || octect == 0x9);
   }
   protected static boolean isPad(char octect) {
       return (octect == PAD);
   }
   protected static boolean isData(char octect) {
       return (octect < BASELENGTH && 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;
       char     encodedData[]     = null;
       encodedData = new char[numberQuartet*4];
       byte k=0, l=0, b1=0,b2=0,b3=0;
       int encodedIndex = 0;
       int dataIndex   = 0;
       if (fDebug) {
           System.out.println("number of triplets = " + numberTriplets );
       }
       for (int i=0; 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;
       }
       return new String(encodedData);
   }
   /**
    * Decodes Base64 data into octects
    *
    * @param encoded string 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 be divisible by four
       }
       int      numberQuadruple    = (len/FOURBYTE );
       if (numberQuadruple == 0)
           return new byte[0];
       byte     decodedData[]      = null;
       byte     b1=0,b2=0,b3=0,b4=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[dataIndex++]) )||
               !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 PAD e.g. 3c[Pad][Pad]
               if ((b2 & 0xf) != 0)//last 4 bits should be 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 be 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;//an 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 removeWhiteSpace(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;
   }

}



 </source>
   
  
 
  



Encodes and decodes to and from Base64 notation.

   <source lang="java">
   

/*

 * JBoss, Home of Professional Open Source
 * Copyright 2005, JBoss Inc., and individual contributors as indicated
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

import java.io.IOException;

/**

* Encodes and decodes to and from Base64 notation.
*
* <p>
* Change Log:
*

*
    *
  • v2.1 - Cleaned up javadoc comments and unused variables and methods. Added * some convenience methods for reading and writing to and from files.
  • *
  • v2.0.2 - Now specifies UTF-8 encoding in places where the code fails on systems * with other encodings (like EBCDIC).
  • *
  • v2.0.1 - Fixed an error when decoding a single byte, that is, when the * encoded data was a single byte.
  • *
  • v2.0 - I got rid of methods that used booleans to set options. * Now everything is more consolidated and cleaner. The code now detects * when data that"s being decoded is gzip-compressed and will decompress it * automatically. Generally things are cleaner. You"ll probably have to * change some method calls that you were making to support the new * options format (ints that you "OR" together).
  • *
  • v1.5.1 - Fixed bug when decompressing and decoding to a * byte[] using decode( String s, boolean gzipCompressed ). * Added the ability to "suspend" encoding in the Output Stream so * you can turn on and off the encoding if you need to embed base64 * data in an otherwise "normal" stream (like an XML file).
  • *
  • v1.5 - Output stream pases on flush() command but doesn"t do anything itself. * This helps when using GZIP streams. * Added the ability to GZip-compress objects before encoding them.
  • *
  • v1.4 - Added helper methods to read/write files.
  • *
  • v1.3.6 - Fixed OutputStream.flush() so that "position" is reset.
  • *
  • v1.3.5 - Added flag to turn on and off line breaks. Fixed bug in input stream * where last buffer being read, if not completely full, was not returned.
  • *
  • v1.3.4 - Fixed when "improperly padded stream" error was thrown at the wrong time.
  • *
  • v1.3.3 - Fixed I/O streams which were totally messed up.
  • *
*
*

* I am placing this code in the Public Domain. Do with it as you will. * This software comes with no guarantees or warranties but with * plenty of well-wishing instead! * Please visit * periodically to check for updates or to contribute improvements. *

*
* @author Robert Harder
* @author rob@iharder.net
* @version 2.1
*/

public class Base64 {

  // provide logging

  /* ********  P U B L I C   F I E L D S  ******** */
  /** No options specified. Value is zero. */
  public final static int NO_OPTIONS = 0;
  /** Specify encoding. */
  public final static int ENCODE = 1;
  /** Specify decoding. */
  public final static int DECODE = 0;
  /** Specify that data should be gzip-compressed. */
  public final static int GZIP = 2;
  /** Don"t break lines when encoding (violates strict Base64 specification) */
  public final static int DONT_BREAK_LINES = 8;
  /* ********  P R I V A T E   F I E L D S  ******** */
  /** Maximum line length (76) of Base64 output. */
  private final static int MAX_LINE_LENGTH = 76;
  /** The equals sign (=) as a byte. */
  private final static byte EQUALS_SIGN = (byte)"=";
  /** The new line character (\n) as a byte. */
  private final static byte NEW_LINE = (byte)"\n";
  /** Preferred encoding. */
  private final static String PREFERRED_ENCODING = "UTF-8";
  /** The 64 valid Base64 values. */
  private final static byte[] ALPHABET;
  private final static byte[] _NATIVE_ALPHABET = /* May be something funny like EBCDIC */
  { (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)"/" };
  /** Determine which ALPHABET to use. */
  static
  {
     byte[] __bytes;
     try
     {
        __bytes = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".getBytes(PREFERRED_ENCODING);
     } // end try
     catch (java.io.UnsupportedEncodingException use)
     {
        __bytes = _NATIVE_ALPHABET; // Fall back to native encoding
     } // end catch
     ALPHABET = __bytes;
  } // end static
  /**
   * Translates a Base64 value to either its 6-bit reconstruction value
   * or a negative number indicating some other meaning.
   **/
  private final static 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
  /*,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 127 - 139
   -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 140 - 152
   -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 153 - 165
   -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 166 - 178
   -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 179 - 191
   -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 192 - 204
   -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 205 - 217
   -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 218 - 230
   -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 231 - 243
   -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9         // Decimal 244 - 255 */
  };
  // I think I end up not using the BAD_ENCODING indicator.
  //private final static byte BAD_ENCODING    = -9; // Indicates error in encoding
  private final static byte WHITE_SPACE_ENC = -5; // Indicates white space in encoding
  private final static byte EQUALS_SIGN_ENC = -1; // Indicates equals sign in encoding
  /** Defeats instantiation. */
  private Base64()
  {
  }
  /* ********  E N C O D I N G   M E T H O D S  ******** */
  /**
   * Encodes up to the first three bytes of array threeBytes
   * and returns a four-byte array in Base64 notation.
   * The actual number of significant bytes in your array is
   * given by numSigBytes.
   * The array threeBytes needs only be as big as
   * numSigBytes.
   * Code can reuse a byte array by passing a four-byte array as b4.
   *
   * @param b4 A reusable byte array to reduce array instantiation
   * @param threeBytes the array to convert
   * @param numSigBytes the number of significant bytes in your array
   * @return four byte array in Base64 notation.
   * @since 1.5.1
   */
  private static byte[] encode3to4(byte[] b4, byte[] threeBytes, int numSigBytes)
  {
     encode3to4(threeBytes, 0, numSigBytes, b4, 0);
     return b4;
  } // end encode3to4
  /**
   * Encodes up to three bytes of the array source
   * and writes the resulting four Base64 bytes to destination.
   * The source and destination arrays can be manipulated
   * anywhere along their length by specifying
   * srcOffset and destOffset.
   * This method does not check to make sure your arrays
   * are large enough to accomodate srcOffset + 3 for
   * the source array or destOffset + 4 for
   * the destination array.
   * The actual number of significant bytes in your array is
   * given by numSigBytes.
   *
   * @param source the array to convert
   * @param srcOffset the index where conversion begins
   * @param numSigBytes the number of significant bytes in your array
   * @param destination the array to hold the conversion
   * @param destOffset the index where output will be put
   * @return the destination array
   * @since 1.3
   */
  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
  /**
   * Serializes an object and returns the Base64-encoded
   * version of that serialized object. If the object
   * cannot be serialized or there is another error,
   * the method will return null.
   * The object is not GZip-compressed before being encoded.
   *
   * @param serializableObject The object to encode
   * @return The Base64-encoded object
   * @since 1.4
   */
  public static String encodeObject(java.io.Serializable serializableObject)
  {
     return encodeObject(serializableObject, NO_OPTIONS);
  } // end encodeObject
  /**
   * Serializes an object and returns the Base64-encoded
   * version of that serialized object. If the object
   * cannot be serialized or there is another error,
   * the method will return null.
*

* Valid options:

    *   GZIP: gzip-compresses object before encoding it.
    *   DONT_BREAK_LINES: don"t break lines at 76 characters
    *     <i>Note: Technically, this makes your encoding non-compliant.</i>
    * 
   * <p>
   * Example: encodeObject( myObj, Base64.GZIP ) or
   * <p>
   * Example: encodeObject( myObj, Base64.GZIP | Base64.DONT_BREAK_LINES )
   *
   * @param serializableObject The object to encode
   * @param options Specified options
   * @return The Base64-encoded object
   * @see Base64#GZIP
   * @see Base64#DONT_BREAK_LINES
   * @since 2.0
   */
  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 Base64.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
  /**
   * Encodes a byte array into Base64 notation.
   * Does not GZip-compress data.
   *
   * @param source The data to convert
   * @return the encode bytes
   * @since 1.4
   */
  public static String encodeBytes(byte[] source)
  {
     return encodeBytes(source, 0, source.length, NO_OPTIONS);
  } // end encodeBytes
  /**
   * Encodes a byte array into Base64 notation.
   * <p>
* Valid options:
    *   GZIP: gzip-compresses object before encoding it.
    *   DONT_BREAK_LINES: don"t break lines at 76 characters
    *     <i>Note: Technically, this makes your encoding non-compliant.</i>
    * 
   * <p>
   * Example: encodeBytes( myData, Base64.GZIP ) or
   * <p>
   * Example: encodeBytes( myData, Base64.GZIP | Base64.DONT_BREAK_LINES )
   *
   *
   * @param source The data to convert
   * @param options Specified options
   * @return the encoded bytes
   * @see Base64#GZIP
   * @see Base64#DONT_BREAK_LINES
   * @since 2.0
   */
  public static String encodeBytes(byte[] source, int options)
  {
     return encodeBytes(source, 0, source.length, options);
  } // end encodeBytes
  /**
   * Encodes a byte array into Base64 notation.
   * Does not GZip-compress data.
   *
   * @param source The data to convert
   * @param off Offset in array where conversion should begin
   * @param len Length of data to convert
   * @return the text node
   * @since 1.4
   */
  public static String encodeBytes(byte[] source, int off, int len)
  {
     return encodeBytes(source, off, len, NO_OPTIONS);
  } // end encodeBytes
  /**
   * Encodes a byte array into Base64 notation.
   * <p>
* Valid options:
    *   GZIP: gzip-compresses object before encoding it.
    *   DONT_BREAK_LINES: don"t break lines at 76 characters
    *     <i>Note: Technically, this makes your encoding non-compliant.</i>
    * 
   * <p>
   * Example: encodeBytes( myData, Base64.GZIP ) or
   * <p>
   * Example: encodeBytes( myData, Base64.GZIP | Base64.DONT_BREAK_LINES )
   *
   *
   * @param source The data to convert
   * @param off Offset in array where conversion should begin
   * @param len Length of data to convert
   * @param options Specified options
   * @see Base64#GZIP
   * @see Base64#DONT_BREAK_LINES
   * @return the text node
   * @since 2.0
   */
  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;
        Base64.OutputStream b64os = null;
        try
        {
           // GZip -> Base64 -> ByteArray
           baos = new java.io.ByteArrayOutputStream();
           b64os = new Base64.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, don"t compress. Better not to use streams at all then.
     else
     {
        // 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
  /* ********  D E C O D I N G   M E T H O D S  ******** */
  /**
   * Decodes four bytes from array source
   * and writes the resulting bytes (up to three of them)
   * to destination.
   * The source and destination arrays can be manipulated
   * anywhere along their length by specifying
   * srcOffset and destOffset.
   * This method does not check to make sure your arrays
   * are large enough to accomodate srcOffset + 4 for
   * the source array or destOffset + 3 for
   * the destination array.
   * This method returns the actual number of bytes that
   * were converted from the Base64 encoding.
   *
   *
   * @param source the array to convert
   * @param srcOffset the index where conversion begins
   * @param destination the array to hold the conversion
   * @param destOffset the index where output will be put
   * @return the number of decoded bytes converted
   * @since 1.3
   */
  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;
     }
     // Example: DkL=
     else if (source[srcOffset + 3] == 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 )
        //              | ( ( 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;
     }
     // Example: DkLE
     else
     {
        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;
        } //end catch
     }
  } // end decodeToBytes
  /**
   * Very low-level access to decoding ASCII characters in
   * the form of a byte array. Does not support automatically
   * gunzipping or any other "fancy" features.
   *
   * @param source The Base64 encoded data
   * @param off    The offset of where to begin decoding
   * @param len    The length of characters to decode
   * @return decoded data
   * @since 1.3
   */
  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
        {
           throw new IllegalStateException("Bad Base64 input character at " + i + ": " + source[i] + "(decimal)");
        } // end else:
     } // each input character
     byte[] out = new byte[outBuffPosn];
     System.arraycopy(outBuff, 0, out, 0, outBuffPosn);
     return out;
  } // end decode
  /**
   * Decodes data from Base64 notation, automatically
   * detecting gzip-compressed data and decompressing it.
   *
   * @param s the string to decode
   * @return the decoded data
   * @since 1.4
   */
  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 = (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
  /**
   * Attempts to decode Base64 data and deserialize a Java
   * Object within. Returns null if there was an error.
   *
   * @param encodedObject The Base64 data to decode
   * @return The decoded and deserialized object
   * @since 1.5
   */
  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;
     } // end catch
     catch (java.lang.ClassNotFoundException e)
     {
        e.printStackTrace();
        obj = null;
     } // end catch
     finally
     {
        try
        {
           bais.close();
        }
        catch (Exception e)
        {
        }
        try
        {
           ois.close();
        }
        catch (Exception e)
        {
        }
     } // end finally
     return obj;
  } // end decodeObject
  /**
   * Convenience method for encoding data to a file.
   *
   * @param dataToEncode byte array of data to encode in base64 form
   * @param filename Filename for saving encoded data
   * @return true if successful, false otherwise
   *
   * @since 2.1
   */
  public static boolean encodeToFile(byte[] dataToEncode, String filename)
  {
     boolean success = false;
     Base64.OutputStream bos = null;
     try
     {
        bos = new Base64.OutputStream(new java.io.FileOutputStream(filename), Base64.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
  /**
   * Convenience method for decoding data to a file.
   *
   * @param dataToDecode Base64-encoded data as a string
   * @param filename Filename for saving decoded data
   * @return true if successful, false otherwise
   *
   * @since 2.1
   */
  public static boolean decodeToFile(String dataToDecode, String filename)
  {
     boolean success = false;
     Base64.OutputStream bos = null;
     try
     {
        bos = new Base64.OutputStream(new java.io.FileOutputStream(filename), Base64.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
  /**
   * Convenience method for reading a base64-encoded
   * file and decoding it.
   *
   * @param filename Filename for reading encoded data
   * @return decoded byte array or null if unsuccessful
   *
   * @since 2.1
   */
  public static byte[] decodeFromFile(String filename)
  {
     byte[] decodedData = null;
     Base64.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)
        {
           throw new IllegalStateException("File is too big for this convenience method (" + file.length() + " bytes).");
        } // end if: file too big for int index
        buffer = new byte[(int)file.length()];
        // Open a stream
        bis = new Base64.InputStream(new java.io.BufferedInputStream(new java.io.FileInputStream(file)), Base64.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)
     {
        throw new IllegalStateException("Error decoding from file " + filename);
     } // end catch: IOException
     finally
     {
        try
        {
           bis.close();
        }
        catch (Exception e)
        {
        }
     } // end finally
     return decodedData;
  } // end decodeFromFile
  /**
   * Convenience method for reading a binary file
   * and base64-encoding it.
   *
   * @param filename Filename for reading binary data
   * @return base64-encoded string or null if unsuccessful
   *
   * @since 2.1
   */
  public static String encodeFromFile(String filename)
  {
     String encodedData = null;
     Base64.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 Base64.InputStream(new java.io.BufferedInputStream(new java.io.FileInputStream(file)), Base64.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, Base64.PREFERRED_ENCODING);
     } // end try
     catch (java.io.IOException e)
     {
        throw new IllegalStateException("Error encoding from file " + filename);
     } // end catch: IOException
     finally
     {
        try
        {
           bis.close();
        }
        catch (Exception e)
        {
        }
     } // end finally
     return encodedData;
  } // end encodeFromFile
  /* ********  I N N E R   C L A S S   I N P U T S T R E A M  ******** */
  /**
   * A {@link Base64.InputStream} will read data from another
   * java.io.InputStream, given in the constructor,
   * and encode/decode to/from Base64 notation on the fly.
   *
   * @see Base64
   * @since 1.3
   */
  public static class InputStream extends java.io.FilterInputStream
  {
     private boolean encode; // Encoding or decoding
     private int position; // Current position in the buffer
     private byte[] buffer; // Small buffer holding converted data
     private int bufferLength; // Length of buffer (3 or 4)
     private int numSigBytes; // Number of meaningful bytes in the buffer
     private int lineLength;
     private boolean breakLines; // Break lines at less than 80 characters
     /**
      * Constructs a {@link Base64.InputStream} in DECODE mode.
      *
      * @param in the java.io.InputStream from which to read data.
      * @since 1.3
      */
     public InputStream(java.io.InputStream in)
     {
        this(in, DECODE);
     } // end constructor
     /**
      * Constructs a {@link Base64.InputStream} in
      * either ENCODE or DECODE mode.
      * <p>
* Valid options:
       *   ENCODE or DECODE: Encode or Decode as data is read.
       *   DONT_BREAK_LINES: don"t break lines at 76 characters
       *     (only meaningful when encoding)
       *     <i>Note: Technically, this makes your encoding non-compliant.</i>
       * 
      * <p>
      * Example: new Base64.InputStream( in, Base64.DECODE )
      *
      *
      * @param in the java.io.InputStream from which to read data.
      * @param options Specified options
      * @see Base64#ENCODE
      * @see Base64#DECODE
      * @see Base64#DONT_BREAK_LINES
      * @since 2.0
      */
     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
     /**
      * Reads enough of the input stream to convert
      * to/from Base64 and returns the next byte.
      *
      * @return next byte
      * @since 1.3
      */
     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 decoding
           else
           {
              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 (/*!encode &&*/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 error
        else
        {
           // 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
     /**
      * Calls {@link #read()} repeatedly until the end of stream
      * is reached or len bytes are read.
      * Returns number of bytes read into array or -1 if
      * end of stream is encountered.
      *
      * @param dest array to hold values
      * @param off offset for array
      * @param len max number of bytes to read into array
      * @return bytes read into array or -1 if end of stream is encountered.
      * @since 1.3
      */
     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
  /* ********  I N N E R   C L A S S   O U T P U T S T R E A M  ******** */
  /**
   * A {@link Base64.OutputStream} will write data to another
   * java.io.OutputStream, given in the constructor,
   * and encode/decode to/from Base64 notation on the fly.
   *
   * @see Base64
   * @since 1.3
   */
  public static class OutputStream extends java.io.FilterOutputStream
  {
     private boolean encode;
     private int position;
     private byte[] buffer;
     private int bufferLength;
     private int lineLength;
     private boolean breakLines;
     private byte[] b4; // Scratch used in a few places
     private boolean suspendEncoding;
     /**
      * Constructs a {@link Base64.OutputStream} in ENCODE mode.
      *
      * @param out the java.io.OutputStream to which data will be written.
      * @since 1.3
      */
     public OutputStream(java.io.OutputStream out)
     {
        this(out, ENCODE);
     } // end constructor
     /**
      * Constructs a {@link Base64.OutputStream} in
      * either ENCODE or DECODE mode.
      * <p>
* Valid options:
       *   ENCODE or DECODE: Encode or Decode as data is read.
       *   DONT_BREAK_LINES: don"t break lines at 76 characters
       *     (only meaningful when encoding)
       *     <i>Note: Technically, this makes your encoding non-compliant.</i>
       * 
      * <p>
      * Example: new Base64.OutputStream( out, Base64.ENCODE )
      *
      * @param out the java.io.OutputStream to which data will be written.
      * @param options Specified options.
      * @see Base64#ENCODE
      * @see Base64#DECODE
      * @see Base64#DONT_BREAK_LINES
      * @since 1.3
      */
     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
     /**
      * Writes the byte to the output stream after
      * converting to/from Base64 notation.
      * When encoding, bytes are buffered three
      * at a time before the output stream actually
      * gets a write() call.
      * When decoding, bytes are buffered four
      * at a time.
      *
      * @param theByte the byte to write
      * @since 1.3
      */
     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, Decoding
        else
        {
           // Meaningful Base64 character?
           if (DECODABET[theByte & 0x7f] > WHITE_SPACE_ENC)
           {
              buffer[position++] = (byte)theByte;
              if (position >= bufferLength) // Enough to output.
              {
                 int len = Base64.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
     /**
      * Calls {@link #write(int)} repeatedly until len
      * bytes are written.
      *
      * @param theBytes array from which to read bytes
      * @param off offset for array
      * @param len max number of bytes to read into array
      * @since 1.3
      */
     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
     /**
      * Method added by PHIL. [Thanks, PHIL. -Rob]
      * This pads the buffer without closing the stream.
      * @throws IOException 
      */
     public void flushBase64() throws java.io.IOException
     {
        if (position > 0)
        {
           if (encode)
           {
              out.write(encode3to4(b4, buffer, position));
              position = 0;
           } // end if: encoding
           else
           {
              throw new java.io.IOException("Base64 input not properly padded.");
           } // end else: decoding
        } // end if: buffer partially full
     } // end flush
     /**
      * Flushes and closes (I think, in the superclass) the stream.
      *
      * @since 1.3
      */
     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
     /**
      * Suspends encoding of the stream.
      * May be helpful if you need to embed a piece of
      * base640-encoded data in a stream.
      *
      * @since 1.5.1
      * @throws IOException 
      */
     public void suspendEncoding() throws java.io.IOException
     {
        flushBase64();
        this.suspendEncoding = true;
     } // end suspendEncoding
     /**
      * Resumes encoding of the stream.
      * May be helpful if you need to embed a piece of
      * base640-encoded data in a stream.
      *
      * @since 1.5.1
      */
     public void resumeEncoding()
     {
        this.suspendEncoding = false;
     } // end resumeEncoding
  } // end inner class OutputStream

} // end class Base64



 </source>
   
  
 
  



Encodes hex octects into Base64

   <source lang="java">
   

/* Copyright 2004 The Apache Software Foundation

*
*   Licensed under the Apache License, Version 2.0 (the "License");
*   you may not use this file except in compliance with the License.
*   You may obtain a copy of the License at
*
*       http://www.apache.org/licenses/LICENSE-2.0
*
*   Unless required by applicable law or agreed to in writing, software
*   distributed under the License is distributed on an "AS IS" BASIS,
*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*   See the License for the specific language governing permissions and
*  limitations under the License.
*/

import java.io.UnsupportedEncodingException; /**

* This class provides encode/decode for RFC 2045 Base64 as
* defined by RFC 2045, N. Freed and N. Borenstein.
* RFC 2045: Multipurpose Internet Mail Extensions (MIME)
* Part One: Format of Internet Message Bodies. Reference
* 1996 Available at: http://www.ietf.org/rfc/rfc2045.txt
* This class is used by XML Schema binary format validation
*
* This implementation does not encode/decode streaming
* data. You need the data that you will encode/decode
* already on a byte arrray.
* 
* 
* From xmlbeans
* @author Jeffrey Rodriguez
* @author Sandy Gao
* @version $Id: Base64.java 111285 2004-12-08 16:54:26Z cezar $
*/

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 byte PAD                = ( byte ) "=";
   static private final boolean fDebug          = false;
   static private byte [] base64Alphabet        = new byte[BASELENGTH];
   static private byte [] lookUpBase64Alphabet  = new byte[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<=25; i++)
           lookUpBase64Alphabet[i] = (byte) ("A"+i );
       for (int i = 26,  j = 0; i<=51; i++, j++)
           lookUpBase64Alphabet[i] = (byte) ("a"+ j );
       for (int i = 52,  j = 0; i<=61; i++, j++)
           lookUpBase64Alphabet[i] = (byte) ("0" + j );
       lookUpBase64Alphabet[62] = (byte) "+";
       lookUpBase64Alphabet[63] = (byte) "/";
   }
   protected static boolean isWhiteSpace(byte octect) {
       return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9);
   }
   protected static boolean isPad(byte octect) {
       return (octect == PAD);
   }
   protected static boolean isData(byte octect) {
       return (base64Alphabet[octect] != -1);
   }
   protected static boolean isBase64(byte octect) {
       return (isWhiteSpace(octect) || isPad(octect) || isData(octect));
   }
   /**
    * Encodes hex octects into Base64
    *
    * @param binaryData Array containing binaryData
    * @return Encoded Base64 array
    */
   public static byte[] encode(byte[] binaryData) {
       if (binaryData == null)
           return null;
       int      lengthDataBits    = binaryData.length*EIGHTBIT;
       int      fewerThan24bits   = lengthDataBits%TWENTYFOURBITGROUP;
       int      numberTriplets    = lengthDataBits/TWENTYFOURBITGROUP;
       byte     encodedData[]     = null;
       if (fewerThan24bits != 0) //data not divisible by 24 bit
           encodedData = new byte[ (numberTriplets + 1 )*4  ];
       else // 16 or 8 bit
           encodedData = new byte[ numberTriplets*4 ];
       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 (i = 0; i<numberTriplets; i++) {
           dataIndex = i*3;
           b1 = binaryData[dataIndex];
           b2 = binaryData[dataIndex + 1];
           b3 = binaryData[dataIndex + 2];
           if (fDebug) {
               System.out.println( "b1= " + b1 +", b2= " + b2 + ", b3= " + b3 );
           }
           l  = (byte)(b2 & 0x0f);
           k  = (byte)(b1 & 0x03);
           encodedIndex = i*4;
           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);
           encodedData[encodedIndex]   = lookUpBase64Alphabet[ val1 ];
           if (fDebug) {
               System.out.println( "val2 = " + val2 );
               System.out.println( "k4   = " + (k<<4));
               System.out.println( "vak  = " + (val2 | (k<<4)));
           }
           encodedData[encodedIndex+1] = lookUpBase64Alphabet[ val2 | ( k<<4 )];
           encodedData[encodedIndex+2] = lookUpBase64Alphabet[ (l <<2 ) | val3 ];
           encodedData[encodedIndex+3] = lookUpBase64Alphabet[ b3 & 0x3f ];
       }
       // form integral number of 6-bit groups
       dataIndex    = i*3;
       encodedIndex = i*4;
       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 + 1] = lookUpBase64Alphabet[ k<<4 ];
           encodedData[encodedIndex + 2] = PAD;
           encodedData[encodedIndex + 3] = 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 + 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 containind decoded data.
    */
   public static byte[] decode(byte[] base64Data) {
       if (base64Data == null)
           return null;
       // remove white spaces
       base64Data = removeWhiteSpace(base64Data);
       if (base64Data.length%FOURBYTE != 0) {
           return null;//should be divisible by four
       }
       int      numberQuadruple    = (base64Data.length/FOURBYTE );
       if (numberQuadruple == 0)
           return new byte[0];
       byte     decodedData[]      = null;
       byte     b1=0,b2=0,b3=0, b4=0;//, marker0=0, marker1=0;
       byte     d1=0,d2=0,d3=0,d4=0;
       // Throw away anything not in normalizedBase64Data
       // Adjust size
       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[dataIndex++]) )||
               !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 PAD e.g. 3c[Pad][Pad]
               if ((b2 & 0xf) != 0)//last 4 bits should be 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 be 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;//an 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;
   }

// /** // * Decodes Base64 data into octects // * // * @param base64Data String containing Base64 data // * @return string containing decoded data. // */ // public static String decode(String base64Data) { // if (base64Data == null) // return null; // // byte[] decoded = null; // try { // decoded = decode(base64Data.getBytes("utf-8")); // } // catch(UnsupportedEncodingException e) { // } // finally { // return decoded == null ? null : new String(decoded); // } // } // // /** // * Encodes octects (using utf-8) into Base64 data // * // * @param binaryData String containing Hex data // * @return string containing decoded data. // */ // public static String encode(String binaryData) { // if (binaryData == null) // return null; // // byte[] encoded = null; // try { // encoded = encode(binaryData.getBytes("utf-8")); // } // catch(UnsupportedEncodingException e) {} // finally { // return encoded == null ? null : new String(encoded); // } // }

   /**
    * remove WhiteSpace from MIME containing encoded Base64 data.
    *
    * @param data  the byte array of base64 data (with WS)
    * @return      the byte array of base64 data (without WS)
    */
   protected static byte[] removeWhiteSpace(byte[] data) {
       if (data == null)
           return null;
       // count characters that"s not whitespace
       int newSize = 0;
       int len = data.length;
       for (int i = 0; i < len; i++) {
           if (!isWhiteSpace(data[i]))
               newSize++;
       }
       // if no whitespace, just return the input array
       if (newSize == len)
           return data;
       // create the array to return
       byte[] newArray = new byte[newSize];
       int j = 0;
       for (int i = 0; i < len; i++) {
           if (!isWhiteSpace(data[i]))
               newArray[j++] = data[i];
       }
       return newArray;
   }

}



 </source>
   
  
 
  



Encoding of raw bytes to base64-encoded characters, and decoding of base64 characters to raw bytes

   <source lang="java">
   

//////////////////////license & copyright header///////////////////////// // // // Base64 - encode/decode data using the Base64 encoding scheme // // // // Copyright (c) 1998 by Kevin Kelley // // // // This library is free software; you can redistribute it and/or // // modify it under the terms of the GNU Lesser General Public // // License as published by the Free Software Foundation; either // // version 2.1 of the License, or (at your option) any later version. // // // // This library is distributed in the hope that it will be useful, // // but WITHOUT ANY WARRANTY; without even the implied warranty of // // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // // GNU Lesser General Public License for more details. // // // // You should have received a copy of the GNU Lesser General Public // // License along with this library; if not, write to the Free Software // // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA // // 02111-1307, USA, or contact the author: // // // // Kevin Kelley <kelley@ruralnet.net> - 30718 Rd. 28, La Junta, CO, // // 81050 USA. // // // ////////////////////end license & copyright header///////////////////////

import java.io.*; // needed only for main() method.

/**

  • Provides encoding of raw bytes to base64-encoded characters, and
  • decoding of base64 characters to raw bytes.
  • @author Kevin Kelley (kelley@ruralnet.net)
  • @version 1.3
  • date 06 August 1998
  • modified 14 February 2000
  • modified 22 September 2000
  • /

public class Base64 { /**

  • returns an array of base64-encoded characters to represent the
  • passed data array.
  • @param data the array of bytes to encode
  • @return base64-coded character array.
  • /

static public char[] encode(byte[] data) {

   char[] out = new char[((data.length + 2) / 3) * 4];
   //
   // 3 bytes encode to 4 chars.  Output is always an even
   // multiple of 4 characters.
   //
   for (int i=0, index=0; i<data.length; i+=3, index+=4) {
       boolean quad = false;
       boolean trip = false;
       int val = (0xFF & (int) data[i]);
       val <<= 8;
       if ((i+1) < data.length) {
           val |= (0xFF & (int) data[i+1]);
           trip = true;
       }
       val <<= 8;
       if ((i+2) < data.length) {
           val |= (0xFF & (int) data[i+2]);
           quad = true;
       }
       out[index+3] = alphabet[(quad? (val & 0x3F): 64)];
       val >>= 6;
       out[index+2] = alphabet[(trip? (val & 0x3F): 64)];
       val >>= 6;
       out[index+1] = alphabet[val & 0x3F];
       val >>= 6;
       out[index+0] = alphabet[val & 0x3F];
   }
   return out;

}

 /**
  * Decodes a BASE-64 encoded stream to recover the original
  * data. White space before and after will be trimmed away,
  * but no other manipulation of the input will be performed.
  *
  * As of version 1.2 this method will properly handle input
  * containing junk characters (newlines and the like) rather
  * than throwing an error. It does this by pre-parsing the
  * input and generating from that a count of VALID input
  * characters.
  **/

static public byte[] decode(char[] data) {

   // as our input could contain non-BASE64 data (newlines,
   // whitespace of any sort, whatever) we must first adjust
   // our count of USABLE data so that...
   // (a) we don"t misallocate the output array, and
   // (b) think that we miscalculated our data length
   //     just because of extraneous throw-away junk
   int tempLen = data.length;
   for( int ix=0; ix<data.length; ix++ )
   {
       if( (data[ix] > 255) || codes[ data[ix] ] < 0 )
           --tempLen;  // ignore non-valid chars and padding
   }
   // calculate required length:
   //  -- 3 bytes for every 4 valid base64 chars
   //  -- plus 2 bytes if there are 3 extra base64 chars,
   //     or plus 1 byte if there are 2 extra.
   int len = (tempLen / 4) * 3;
   if ((tempLen % 4) == 3) len += 2;
   if ((tempLen % 4) == 2) len += 1;
   byte[] out = new byte[len];
   int shift = 0;   // # of excess bits stored in accum
   int accum = 0;   // excess bits
   int index = 0;
   // we now go through the entire array (NOT using the "tempLen" value)
   for (int ix=0; ix<data.length; ix++)
   {
       int value = (data[ix]>255)? -1: codes[ data[ix] ];
       if ( value >= 0 )           // skip over non-code
       {
           accum <<= 6;            // bits shift up by 6 each time thru
           shift += 6;             // loop, with new bits being put in
           accum |= value;         // at the bottom.
           if ( shift >= 8 )       // whenever there are 8 or more shifted in,
           {
               shift -= 8;         // write them out (from the top, leaving any
               out[index++] =      // excess at the bottom for next iteration.
                   (byte) ((accum >> shift) & 0xff);
           }
       }
       // we will also have skipped processing a padding null byte ("=") here;
       // these are used ONLY for padding to an even length and do not legally
       // occur as encoded data. for this reason we can ignore the fact that
       // no index++ operation occurs in that special case: the out[] array is
       // initialized to all-zero bytes to start with and that works to our
       // advantage in this combination.
   }
   // if there is STILL something wrong we just have to throw up now!
   if( index != out.length)
   {
       throw new Error("Miscalculated data length (wrote " + index + " instead of " + out.length + ")");
   }
   return out;

}

// // code characters for values 0..63 // static private char[] alphabet =

   "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
       .toCharArray();

// // lookup table for converting base64 characters to value in range 0..63 // static private byte[] codes = new byte[256]; static {

   for (int i=0; i<256; i++) codes[i] = -1;
   for (int i = "A"; i <= "Z"; i++) codes[i] = (byte)(     i - "A");
   for (int i = "a"; i <= "z"; i++) codes[i] = (byte)(26 + i - "a");
   for (int i = "0"; i <= "9"; i++) codes[i] = (byte)(52 + i - "0");
   codes["+"] = 62;
   codes["/"] = 63;

}


/////////////////////////////////////////////////// // remainder (main method and helper functions) is // for testing purposes only, feel free to clip it. /////////////////////////////////////////////////// public static void main(String[] args) {

   boolean decode = false;
   if (args.length == 0) {
       System.out.println("usage:  java Base64 [-d[ecode]] filename");
       System.exit(0);
   }
   for (int i=0; i<args.length; i++) {
       if ("-decode".equalsIgnoreCase(args[i])) decode = true;
       else if ("-d".equalsIgnoreCase(args[i])) decode = true;
   }
   String filename = args[args.length-1];
   File file = new File(filename);
   if (!file.exists()) {
       System.out.println("Error:  file "" + filename + "" doesn"t exist!");
       System.exit(0);
   }
   if (decode)
   {
       char[] encoded = readChars(file);
       byte[] decoded = decode(encoded);
       writeBytes(file, decoded);
   }
   else
   {
       byte[] decoded = readBytes(file);
       char[] encoded = encode(decoded);
       writeChars(file, encoded);
   }

} private static byte[] readBytes(File file) {

   ByteArrayOutputStream baos = new ByteArrayOutputStream();
   try
   {
       InputStream fis = new FileInputStream(file);
       InputStream is = new BufferedInputStream(fis);
       int count = 0;
       byte[] buf = new byte[16384];
       while ((count=is.read(buf)) != -1) {
           if (count > 0) baos.write(buf, 0, count);
       }
       is.close();
   }
   catch (Exception e) { e.printStackTrace(); }
   return baos.toByteArray();

} private static char[] readChars(File file) {

   CharArrayWriter caw = new CharArrayWriter();
   try
   {
       Reader fr = new FileReader(file);
       Reader in = new BufferedReader(fr);
       int count = 0;
       char[] buf = new char[16384];
       while ((count=in.read(buf)) != -1) {
           if (count > 0) caw.write(buf, 0, count);
       }
       in.close();
   }
   catch (Exception e) { e.printStackTrace(); }
   return caw.toCharArray();

} private static void writeBytes(File file, byte[] data) {

   try {
       OutputStream fos = new FileOutputStream(file);
       OutputStream os = new BufferedOutputStream(fos);
       os.write(data);
       os.close();
   }
   catch (Exception e) { e.printStackTrace(); }

} private static void writeChars(File file, char[] data) {

   try {
       Writer fos = new FileWriter(file);
       Writer os = new BufferedWriter(fos);
       os.write(data);
       os.close();
   }
   catch (Exception e) { e.printStackTrace(); }

}

}



 </source>
   
  
 
  



Helper class to provide Base64 encoding routines.

   <source lang="java">
   

/*******************************************************************************

* Copyright (C) 2006 Google Inc.
* 
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* 
* http://www.apache.org/licenses/LICENSE-2.0
* 
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
******************************************************************************/

/**

* Helper class to provide Base64 encoding routines.
* 
* @author ? - added by ksim
* @date March 6th, 2007
* @version 1.0
* @todo Not unit tested yet.
*/

/**

* The Base64Coder class provides methods for encoding strings and byte
* arrays into Base64 format. It also provides methods for decoding
* Base64-encoded strings and character arrays.
* 
* @version 1.0 beta
*/

public class Base64Coder {

 private Base64Coder() {
 }
 /**
  * Mapping table from 6-bit nibbles to Base64 characters.
  */
 private static char[] map1 = new char[64];
 static {
   int i = 0;
   for (char c = "A"; c <= "Z"; c++) {
     map1[i++] = c;
   }
   for (char c = "a"; c <= "z"; c++) {
     map1[i++] = c;
   }
   for (char c = "0"; c <= "9"; c++) {
     map1[i++] = c;
   }
   map1[i++] = "+";
   map1[i++] = "/";
 }
 /**
  * Mapping table from Base64 characters to 6-bit nibbles.
  */
 private static byte[] map2 = new byte[128];
 static {
   for (int i = 0; i < map2.length; i++) {
     map2[i] = -1;
   }
   for (int i = 0; i < 64; i++) {
     map2[map1[i]] = (byte) i;
   }
 }
 /**
  * The encode (String s) method encodes a string into Base64 format.
  * No blanks or line breaks are inserted.
  * 
  * @param s
  *            The string to be encoded.
  * @return String in Base64-encoded format.
  */
 public static String encode(String s) {
   return new String(encode(s.getBytes()));
 }
 /**
  * The encode (byte[] in) method encodes a byte array into Base64
  * format. No blanks or line breaks are inserted.
  * 
  * @param in
  *            An array containing the data bytes to be encoded.
  * @return A character array containing the Base64-encoded data.
  */
 public static char[] encode(byte[] in) {
   int iLen = in.length;
   int oDataLen = (iLen * 4 + 2) / 3; // output length without padding
   int oLen = ((iLen + 2) / 3) * 4; // output length including padding
   char[] out = new char[oLen];
   int ip = 0;
   int op = 0;
   while (ip < iLen) {
     int i0 = in[ip++] & 0xff;
     int i1 = ip < iLen ? in[ip++] & 0xff : 0;
     int i2 = ip < iLen ? in[ip++] & 0xff : 0;
     int o0 = i0 >>> 2;
     int o1 = ((i0 & 3) << 4) | (i1 >>> 4);
     int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6);
     int o3 = i2 & 0x3F;
     out[op++] = map1[o0];
     out[op++] = map1[o1];
     out[op] = op < oDataLen ? map1[o2] : "=";
     op++;
     out[op] = op < oDataLen ? map1[o3] : "=";
     op++;
   }
   return out;
 }
 /**
  * The decode (String s) method decodes a Base64-encoded string.
  * 
  * @param s
  *            The Base64 String to be decoded.
  * @return A String containing the decoded data.
  * @throws IllegalArgumentException
  *             if the input is not valid Base64-encoded data.
  */
 public static String decode(String s) {
   return new String(decode(s.toCharArray()));
 }
 /**
  * The decode (char[] in) method decodes an array of Base64-encoded
  * characters. No blanks or line breaks are allowed within the
  * Base64-encoded data.
  * 
  * @param in
  *            A character array containing the Base64-encoded data.
  * @return An array containing the decoded data bytes.
  * @throws IllegalArgumentException
  *             if the input is not valid Base64-encoded data.
  */
 public static byte[] decode(char[] in) {
   int iLen = in.length;
   if (iLen % 4 != 0)
     throw new IllegalArgumentException(
         "Length of Base64 encoded input "
             + "string is not a multiple of 4.");
   while (iLen > 0 && in[iLen - 1] == "=")
     iLen--;
   int oLen = (iLen * 3) / 4;
   byte[] out = new byte[oLen];
   int ip = 0;
   int op = 0;
   while (ip < iLen) {
     int i0 = in[ip++];
     int i1 = in[ip++];
     int i2 = ip < iLen ? in[ip++] : "A";
     int i3 = ip < iLen ? in[ip++] : "A";
     if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127)
       throw new IllegalArgumentException("Illegal character in "
           + "Base64 encoded data.");
     int b0 = map2[i0];
     int b1 = map2[i1];
     int b2 = map2[i2];
     int b3 = map2[i3];
     if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0)
       throw new IllegalArgumentException(
           "Illegal character in Base64 " + "encoded data.");
     int o0 = (b0 << 2) | (b1 >>> 4);
     int o1 = ((b1 & 0xf) << 4) | (b2 >>> 2);
     int o2 = ((b2 & 3) << 6) | b3;
     out[op++] = (byte) o0;
     if (op < oLen) {
       out[op++] = (byte) o1;
     }
     if (op < oLen) {
       out[op++] = (byte) o2;
     }
   }
   return out;
 }

}



 </source>
   
  
 
  



Implementation of MIME"s Base64 encoding and decoding conversions.

   <source lang="java">
   

/*

* Copyright  1999-2004 The Apache Software Foundation.
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*
*/

public class Base64 {

 /**
  * Implementation of MIME"s Base64 encoding and decoding conversions.
  * Optimized code. (raw version taken from oreilly.jonathan.util, and
  * currently org.apache.xerces.ds.util.Base64)
  * 
  * @author Raul Benito(Of the xerces copy, and little adaptations).
  * @author Anli Shundi
  * @author Christian Geuer-Pollmann
  * @see 
  * @see org.apache.xml.security.transforms.implementations.TransformBase64Decode
  */
 /**
  * Field BASE64DEFAULTLENGTH
  */
 public static final int BASE64DEFAULTLENGTH = 76;
 /**
  * Field _base64length
  */
 static int _base64length = Base64.BASE64DEFAULTLENGTH;
 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 FOURBYTE = 4;
 static private final int SIGN = -128;
 static private final char PAD = "=";
 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 <= 25; i++)
     lookUpBase64Alphabet[i] = (char) ("A" + i);
   for (int i = 26, j = 0; i <= 51; i++, j++)
     lookUpBase64Alphabet[i] = (char) ("a" + j);
   for (int i = 52, j = 0; i <= 61; i++, j++)
     lookUpBase64Alphabet[i] = (char) ("0" + j);
   lookUpBase64Alphabet[62] = "+";
   lookUpBase64Alphabet[63] = "/";
 }
 private Base64() {
   // we don"t allow instantiation
 }
 /**
  * Encode a byte array and fold lines at the standard 76th character.
  * 
  * @param binaryData
  *          byte[]<code> to be base64 encoded
  * @return the <code>String<code> with encoded data
  */
 public static String encode(byte[] binaryData) {
   return encode(binaryData, BASE64DEFAULTLENGTH, false);
 }
 protected static boolean isWhiteSpace(byte octect) {
   return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9);
 }
 protected static boolean isPad(byte octect) {
   return (octect == PAD);
 }
 /**
  * Encode a byte array in Base64 format and return an optionally wrapped line.
  * 
  * @param binaryData
  *          <code>byte[] data to be encoded
  * @param length
  *          int<code> length of wrapped lines; No wrapping if less than 4.
  * @return a <code>String with encoded data
  */
 public static String encode(byte[] binaryData, int length, boolean wrap) {
   if (length < 4) {
     length = Integer.MAX_VALUE;
   }
   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 quartesPerLine = length / 4;
   int numberLines = (numberQuartet - 1) / quartesPerLine;
   char encodedData[];
   encodedData = new char[(numberQuartet * 4) + (wrap ? numberLines : 0)];
   byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
   int encodedIndex = 0;
   int dataIndex = 0;
   int tripletsDone = 0;
   for (int line = 0; line < numberLines; line++) {
     for (int quartet = 0; quartet < quartesPerLine; quartet++) {
       b1 = binaryData[dataIndex++];
       b2 = binaryData[dataIndex++];
       b3 = binaryData[dataIndex++];
       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);
       encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
       encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
       encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3];
       encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f];
       tripletsDone++;
     }
     if (wrap) {
       encodedData[encodedIndex++] = 0xa;
     }
   }
   for (; tripletsDone < numberTriplets; tripletsDone++) {
     b1 = binaryData[dataIndex++];
     b2 = binaryData[dataIndex++];
     b3 = binaryData[dataIndex++];
     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);
     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);
     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;
   }
   return new String(encodedData);
 }
 /**
  * Decodes Base64 data into octects
  * 
  * @param encoded
  *          String containing Base64 data
  * @return Array containing decoded data.
  */
 public static byte[] decode(String encoded) throws RuntimeException {
   byte[] base64Data = encoded.getBytes();
   // remove white spaces
   int len = removeWhiteSpace(base64Data);
   if (len % FOURBYTE != 0) {
     throw new RuntimeException("decoding.divisible.four");
     // should be divisible by four
   }
   int numberQuadruple = (len / FOURBYTE);
   if (numberQuadruple == 0)
     return new byte[0];
   byte decodedData[] = null;
   byte b1 = 0, b2 = 0, b3 = 0, b4 = 0;
   int i = 0;
   int encodedIndex = 0;
   int dataIndex = 0;
   // decodedData = new byte[ (numberQuadruple)*3];
   dataIndex = (numberQuadruple - 1) * 4;
   encodedIndex = (numberQuadruple - 1) * 3;
   // first last bits.
   b1 = base64Alphabet[base64Data[dataIndex++]];
   b2 = base64Alphabet[base64Data[dataIndex++]];
   if ((b1 == -1) || (b2 == -1)) {
     throw new RuntimeException("decoding.general");// if found "no data" just
                                                     // return null
   }
   byte d3, d4;
   b3 = base64Alphabet[d3 = base64Data[dataIndex++]];
   b4 = base64Alphabet[d4 = base64Data[dataIndex++]];
   if ((b3 == -1) || (b4 == -1)) {
     // Check if they are PAD characters
     if (isPad(d3) && isPad(d4)) { // Two PAD e.g. 3c[Pad][Pad]
       if ((b2 & 0xf) != 0)// last 4 bits should be zero
         throw new RuntimeException("decoding.general");
       decodedData = new byte[encodedIndex + 1];
       decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
     } else if (!isPad(d3) && isPad(d4)) { // One PAD e.g. 3cQ[Pad]
       if ((b3 & 0x3) != 0)// last 2 bits should be zero
         throw new RuntimeException("decoding.general");
       decodedData = new byte[encodedIndex + 2];
       decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
       decodedData[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
     } else {
       throw new RuntimeException("decoding.general");// an error like
                                                       // "3c[Pad]r", "3cdX",
                                                       // "3cXd", "3cXX" where
                                                       // X is non data
     }
   } else {
     // No PAD e.g 3cQl
     decodedData = new byte[encodedIndex + 3];
     decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
     decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
     decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
   }
   encodedIndex = 0;
   dataIndex = 0;
   // the begin
   for (i = numberQuadruple - 1; i > 0; i--) {
     b1 = base64Alphabet[base64Data[dataIndex++]];
     b2 = base64Alphabet[base64Data[dataIndex++]];
     b3 = base64Alphabet[base64Data[dataIndex++]];
     b4 = base64Alphabet[base64Data[dataIndex++]];
     if ((b1 == -1) || (b2 == -1) || (b3 == -1) || (b4 == -1)) {
       throw new RuntimeException("decoding.general");// if found "no data"
                                                       // just return null
     }
     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 removeWhiteSpace(byte[] 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++) {
     byte dataS = data[i];
     if (!isWhiteSpace(dataS))
       data[newSize++] = dataS;
   }
   return newSize;
 }
 /**
  * @param args
  */
 public static void main(String[] args) {
   // TODO Auto-generated method stub
 }

}



 </source>
   
  
 
  



One of the fastest implementation of the Base64 encoding. Jakarta and others are slower

   <source lang="java">
    

// Copyright (c) 2003-2009, Jodd Team (jodd.org). All Rights Reserved.

import java.io.IOException; import java.io.OutputStream; import java.io.Writer; /**

* One of the fastest implementation of the Base64 encoding.
* Jakarta and others are slower.
*/

public class Base64 {

 private static final char[] S_BASE64CHAR = {
   "A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
   "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
   "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d",
   "e", "f", "g", "h", "i", "j", "k", "l", "m", "n",
   "o", "p", "q", "r", "s", "t", "u", "v", "w", "x",
   "y", "z", "0", "1", "2", "3", "4", "5", "6", "7",
   "8", "9", "+", "/"
 };
 private static final char S_BASE64PAD = "=";
 private static final byte[] S_DECODETABLE = new byte[128];
 static {
   for (int i = 0;  i < S_DECODETABLE.length;  i ++) {
     S_DECODETABLE[i] = Byte.MAX_VALUE;          // 127
   }
   for (int i = 0;  i < S_BASE64CHAR.length;  i ++)    // 0 to 63
   {
     S_DECODETABLE[S_BASE64CHAR[i]] = (byte) i;
   }
 }
 private static int decode0(char[] ibuf, byte[] obuf, int wp) {
   int outlen = 3;
   if (ibuf[3] == S_BASE64PAD) {
     outlen = 2;
   }
   if (ibuf[2] == S_BASE64PAD) {
     outlen = 1;
   }
   int b0 = S_DECODETABLE[ibuf[0]];
   int b1 = S_DECODETABLE[ibuf[1]];
   int b2 = S_DECODETABLE[ibuf[2]];
   int b3 = S_DECODETABLE[ibuf[3]];
   switch (outlen) {
     case 1:
     obuf[wp] = (byte) (b0 << 2 & 0xfc | b1 >> 4 & 0x3);
     return 1;
     case 2:
     obuf[wp++] = (byte) (b0 << 2 & 0xfc | b1 >> 4 & 0x3);
     obuf[wp] = (byte) (b1 << 4 & 0xf0 | b2 >> 2 & 0xf);
     return 2;
     case 3:
     obuf[wp++] = (byte) (b0 << 2 & 0xfc | b1 >> 4 & 0x3);
     obuf[wp++] = (byte) (b1 << 4 & 0xf0 | b2 >> 2 & 0xf);
     obuf[wp] = (byte) (b2 << 6 & 0xc0 | b3 & 0x3f);
     return 3;
     default:
     throw new RuntimeException("Internal Error");
   }
 }
 
 /**
  * Decode the base64 data.
  * @param data The base64 encoded data to be decoded
  * @param off The offset within the encoded data at which to start decoding
  * @param len The length of data to decode
  * @return The decoded data
  */
 public static byte[] decode(char[] data, int off, int len) {
   char[] ibuf = new char[4];
   int ibufcount = 0;
   byte[] obuf = new byte[(len >> 2) * 3 + 3];
   int obufcount = 0;
   for (int i = off;  i < off+len;  i ++) {
     char ch = data[i];
     if (ch == S_BASE64PAD || ch < S_DECODETABLE.length && S_DECODETABLE[ch] != Byte.MAX_VALUE) {
       ibuf[ibufcount++] = ch;
       if (ibufcount == ibuf.length) {
         ibufcount = 0;
         obufcount += decode0(ibuf, obuf, obufcount);
       }
     }
   }
   if (obufcount == obuf.length) {
     return obuf;
   }
   byte[] ret = new byte[obufcount];
   System.arraycopy(obuf, 0, ret, 0, obufcount);
   return ret;
 }
 public static final int BUF_SIZE =  256;
 /**
  * Decode the base64 data.
  * @param data The base64 encoded data to be decoded
  * @return The decoded data
  */
 public static byte[] decode(String data) {
   int ibufcount = 0;
   int slen = data.length();
   char[] ibuf = new char[slen < BUF_SIZE +3 ? slen : BUF_SIZE + 3];
   byte[] obuf = new byte[(slen >> 2) *3+3];
   int obufcount = 0;
   int blen;
 
   for (int i = 0;  i < slen;  i +=BUF_SIZE ) {
     // buffer may contain unprocessed characters from previous step
     if (i + BUF_SIZE  <= slen)  {
       data.getChars(i, i+BUF_SIZE , ibuf, ibufcount);
       blen = BUF_SIZE + ibufcount;
     } else {
       data.getChars(i, slen, ibuf, ibufcount);
       blen = slen - i+ibufcount;
     }
 
     for (int j=ibufcount; j<blen; j++) {
       char ch = ibuf[j];
       if (ch == S_BASE64PAD || ch < S_DECODETABLE.length && S_DECODETABLE[ch] != Byte.MAX_VALUE) {
         ibuf[ibufcount++] = ch;
         // as soon as we have 4 chars process them
         if (ibufcount == 4) {
           ibufcount = 0;
           obufcount += decode0(ibuf, obuf, obufcount);
         }
       }
     }
   }
   if (obufcount == obuf.length) {
     return obuf;
   }
   byte[] ret = new byte[obufcount];
   System.arraycopy(obuf, 0, ret, 0, obufcount);
   return ret;
 }
 /**
  * Decode the base64 data.
  * @param data The base64 encoded data to be decoded
  * @param off The offset within the encoded data at which to start decoding
  * @param len The length of data to decode
  * @param ostream The OutputStream to which the decoded data should be
  *                written
  */
 public static void decode(char[] data, int off, int len, OutputStream ostream) throws IOException {
   char[] ibuf = new char[4];
   int ibufcount = 0;
   byte[] obuf = new byte[3];
   for (int i = off;  i < off+len;  i ++) {
     char ch = data[i];
     if (ch == S_BASE64PAD || ch < S_DECODETABLE.length && S_DECODETABLE[ch] != Byte.MAX_VALUE) {
       ibuf[ibufcount++] = ch;
       if (ibufcount == ibuf.length) {
         ibufcount = 0;
         int obufcount = decode0(ibuf, obuf, 0);
         ostream.write(obuf, 0, obufcount);
       }
     }
   }
 }
 
 /**
  * Decode the base64 data.
  * @param data The base64 encoded data to be decoded
  * @param ostream The OutputStream to which the decoded data should be
  *                written
  */
 public static void decode(String data, OutputStream ostream) throws IOException {
   char[] ibuf = new char[BUF_SIZE + 4];
   byte[] obuf = new byte[3];
   int slen = data.length();
   int blen;
   int ibufcount = 0;
 
   for (int i = 0;  i < slen;  i +=BUF_SIZE ) {
     // buffer may contain unprocessed characters from previous step
     if (i + BUF_SIZE  <= slen)  {
       data.getChars(i, i + BUF_SIZE , ibuf, ibufcount);
       blen = BUF_SIZE+ibufcount;
     } else {
       data.getChars(i, slen, ibuf, ibufcount);
       blen = slen - i+ibufcount;
     }
 
     for (int j=ibufcount; j<blen; j++) {
       char ch = ibuf[j];
       if (ch == S_BASE64PAD || ch < S_DECODETABLE.length && S_DECODETABLE[ch] != Byte.MAX_VALUE) {
         ibuf[ibufcount++] = ch;
         
         // as sson as we have 4 chars process them
         if (ibufcount == 4) {
           ibufcount = 0;
           int obufcount = decode0(ibuf, obuf, 0);
           ostream.write(obuf, 0, obufcount);
         }
       }
     }
   }
 }
 /**
  * Returns base64 representation of specified byte array.
  * @param data The data to be encoded
  * @return The base64 encoded data
  */
 public static String encode(byte[] data) {
   return encode(data, 0, data.length);
 }
 public static String encode(String s) {
   return encode(s.getBytes(), 0, s.length());
 }
 /**
  * Returns base64 representation of specified byte array.
  * @param data The data to be encoded
  * @param off The offset within the data at which to start encoding
  * @param len The length of the data to encode
  * @return The base64 encoded data
  */
 public static String encode(byte[] data, int off, int len) {
   if (len <= 0) {
     return "";
   }
   char[] out = new char[(len / 3 << 2) +4];
   int rindex = off;
   int windex = 0;
   int rest = len;
   while (rest >= 3) {
     int i = ((data[rindex]&0xff)<<16)
       +((data[rindex+1]&0xff)<<8)
       +(data[rindex+2]&0xff);
     out[windex++] = S_BASE64CHAR[i>>18];
     out[windex++] = S_BASE64CHAR[(i>>12)&0x3f];
     out[windex++] = S_BASE64CHAR[(i>>6)&0x3f];
     out[windex++] = S_BASE64CHAR[i&0x3f];
     rindex += 3;
     rest -= 3;
   }
   if (rest == 1) {
     int i = data[rindex]&0xff;
     out[windex++] = S_BASE64CHAR[i>>2];
     out[windex++] = S_BASE64CHAR[(i<<4)&0x3f];
     out[windex++] = S_BASE64PAD;
     out[windex++] = S_BASE64PAD;
   } else if (rest == 2) {
     int i = ((data[rindex]&0xff)<<8)+(data[rindex+1]&0xff);
     out[windex++] = S_BASE64CHAR[i>>10];
     out[windex++] = S_BASE64CHAR[(i>>4)&0x3f];
     out[windex++] = S_BASE64CHAR[(i<<2)&0x3f];
     out[windex++] = S_BASE64PAD;
   }
   return new String(out, 0, windex);
 }
 /**
  * Outputs base64 representation of the specified byte array to a byte stream.
  * @param data The data to be encoded
  * @param off The offset within the data at which to start encoding
  * @param len The length of the data to encode
  * @param ostream The OutputStream to which the encoded data should be
  *                written
  */
 public static void encode(byte[] data, int off, int len, OutputStream ostream) throws IOException {
   if (len <= 0) {
     return;
   }
   byte[] out = new byte[4];
   int rindex = off;
   int rest = len;
   while (rest >= 3) {
     int i = ((data[rindex]&0xff)<<16)
       +((data[rindex+1]&0xff)<<8)
       +(data[rindex+2]&0xff);
     out[0] = (byte)S_BASE64CHAR[i>>18];
     out[1] = (byte)S_BASE64CHAR[(i>>12)&0x3f];
     out[2] = (byte)S_BASE64CHAR[(i>>6)&0x3f];
     out[3] = (byte)S_BASE64CHAR[i&0x3f];
     ostream.write(out, 0, 4);
     rindex += 3;
     rest -= 3;
   }
   if (rest == 1) {
     int i = data[rindex]&0xff;
     out[0] = (byte)S_BASE64CHAR[i>>2];
     out[1] = (byte)S_BASE64CHAR[(i<<4)&0x3f];
     out[2] = (byte)S_BASE64PAD;
     out[3] = (byte)S_BASE64PAD;
     ostream.write(out, 0, 4);
   } else if (rest == 2) {
     int i = ((data[rindex]&0xff)<<8)+(data[rindex+1]&0xff);
     out[0] = (byte)S_BASE64CHAR[i>>10];
     out[1] = (byte)S_BASE64CHAR[(i>>4)&0x3f];
     out[2] = (byte)S_BASE64CHAR[(i<<2)&0x3f];
     out[3] = (byte)S_BASE64PAD;
     ostream.write(out, 0, 4);
   }
 }
 
 /**
  * Outputs base64 representation of the specified byte array to a character stream.
  * @param data The data to be encoded
  * @param off The offset within the data at which to start encoding
  * @param len The length of the data to encode
  * @param writer The Writer to which the encoded data should be
  *               written
  */
 public static void encode(byte[] data, int off, int len, Writer writer) throws IOException {
   if (len <= 0) {
     return;
   }
   char[] out = new char[4];
   int rindex = off;
   int rest = len;
   int output = 0;
   while (rest >= 3) {
     int i = ((data[rindex]&0xff)<<16) +((data[rindex+1]&0xff)<<8) +(data[rindex+2]&0xff);
     out[0] = S_BASE64CHAR[i>>18];
     out[1] = S_BASE64CHAR[(i>>12)&0x3f];
     out[2] = S_BASE64CHAR[(i>>6)&0x3f];
     out[3] = S_BASE64CHAR[i&0x3f];
     writer.write(out, 0, 4);
     rindex += 3;
     rest -= 3;
     output += 4;
     if (output % 76 == 0) {
       writer.write("\n");
     }
   }
   if (rest == 1) {
     int i = data[rindex]&0xff;
     out[0] = S_BASE64CHAR[i>>2];
     out[1] = S_BASE64CHAR[(i<<4)&0x3f];
     out[2] = S_BASE64PAD;
     out[3] = S_BASE64PAD;
     writer.write(out, 0, 4);
   } else if (rest == 2) {
     int i = ((data[rindex]&0xff)<<8)+(data[rindex+1]&0xff);
     out[0] = S_BASE64CHAR[i>>10];
     out[1] = S_BASE64CHAR[(i>>4)&0x3f];
     out[2] = S_BASE64CHAR[(i<<2)&0x3f];
     out[3] = S_BASE64PAD;
     writer.write(out, 0, 4);
   }
 }

}



 </source>
   
  
 
  



Performs Base64 encoding and/or decoding

   <source lang="java">
   

/*

* Copyright 1999,2005 The Apache Software Foundation.
* 
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* 
*      http://www.apache.org/licenses/LICENSE-2.0
* 
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.StringWriter; import java.io.Writer; import java.lang.reflect.UndeclaredThrowableException; import org.xml.sax.ContentHandler; import org.xml.sax.SAXException;

/** Performs Base64 encoding and/or decoding. This is an on-the-fly decoder: Unlike,

* for example, the commons-codec classes, it doesn"t depend on byte arrays. In
* other words, it has an extremely low memory profile. This is well suited even
* for very large byte streams.
*/

public class Base64 {

 /** An exception of this type is thrown, if the decoded
  * character stream contains invalid input.
  */
 public static class DecodingException extends IOException {
   private static final long serialVersionUID = 3257006574836135478L;
   DecodingException(String pMessage) { super(pMessage); }
 }
 /** An exception of this type is thrown by the {@link SAXEncoder},
  * if writing to the target handler causes a SAX exception.
  * This class is required, because the {@link IOException}
  * allows no cause until Java 1.3.
  */
 public static class SAXIOException extends IOException {
   private static final long serialVersionUID = 3258131345216451895L;
   final SAXException saxException;
   SAXIOException(SAXException e) {
     super();
     saxException = e;
   }
   /** Returns the encapsulated {@link SAXException}.
    * @return An exception, which was thrown when invoking
    * {@link ContentHandler#characters(char[], int, int)}.
    */
   public SAXException getSAXException() { return saxException; }
 }
 /** Default line separator: \n
  */
 public static final String LINE_SEPARATOR = "\n";
 /** Default size for line wrapping.
  */
 public static final int LINE_SIZE = 76;
 /**
    * This array is a lookup table that translates 6-bit positive integer
    * index values into their "Base64 Alphabet" equivalents as specified 
    * in Table 1 of RFC 2045.
    */
   private static final char intToBase64[] = {
       "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
       "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
       "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
       "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
       "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "+", "/"
   };
   /**
    * This array is a lookup table that translates unicode characters
    * drawn from the "Base64 Alphabet" (as specified in Table 1 of RFC 2045)
    * into their 6-bit positive integer equivalents.  Characters that
    * are not in the Base64 alphabet but fall within the bounds of the
    * array are translated to -1.
    */
   private static final byte base64ToInt[] = {
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54,
       55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 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, -1, -1, -1, -1, -1, -1, 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
   };
 /** An encoder is an object, which is able to encode byte array
  * in blocks of three bytes. Any such block is converted into an
  * array of four bytes.
  */
 public static abstract class Encoder {
   private int num, numBytes;
   private final char[] charBuffer;
   private int charOffset;
   private final int wrapSize;
   private final int skipChars;
   private final String sep;
   private int lineChars = 0;
   /** Creates a new instance.
    * @param pBuffer The encoders buffer. The encoder will
    * write to the buffer as long as possible. If the
    * buffer is full or the end of data is signaled, then
    * the method {@link #writeBuffer(char[], int, int)}
    * will be invoked.
    * @param pWrapSize A nonzero value indicates, that a line
    * wrap should be performed after the given number of
    * characters. The value must be a multiple of 4. Zero
    * indicates, that no line wrap should be performed.
    * @param pSep The eol sequence being used to terminate
    * a line in case of line wraps. May be null, in which
    * case the default value {@link Base64#LINE_SEPARATOR}
    * is being used.
    */
   protected Encoder(char[] pBuffer, int pWrapSize, String pSep) {
     charBuffer = pBuffer;
     sep = pSep == null ? null : Base64.LINE_SEPARATOR;
     skipChars = pWrapSize == 0 ? 4 : 4 + sep.length();
     wrapSize = skipChars == 4 ? 0 : pWrapSize;
     if (wrapSize < 0  ||  wrapSize %4 > 0) {
       throw new IllegalArgumentException("Illegal argument for wrap size: " + pWrapSize
                          + "(Expected nonnegative multiple of 4)");
     }
     if (pBuffer.length < skipChars) {
       throw new IllegalArgumentException("The buffer must contain at least " + skipChars
                          + " characters, but has " + pBuffer.length);
     }
   }
   /** Called for writing the buffer contents to the target.
    * @param pChars The buffer being written.
    * @param pOffset Offset of first character being written.
    * @param pLen Number of characters being written.
    * @throws IOException Writing to the destination failed.
    */
   protected abstract void writeBuffer(char[] pChars, int pOffset, int pLen) throws IOException;
   private void wrap() {
     for (int j = 0;  j < sep.length();  j++) {
       charBuffer[charOffset++] = sep.charAt(j);
     }
     lineChars = 0;
   }
   /** Encodes the given byte array.
    * @param pBuffer Byte array being encoded.
    * @param pOffset Offset of first byte being encoded.
    * @param pLen Number of bytes being encoded.
    * @throws IOException Invoking the {@link #writeBuffer(char[],int,int)} method
    * for writing the encoded data failed.
    */
   public void write(byte[] pBuffer, int pOffset, int pLen) throws IOException {
     for(int i = 0;  i < pLen;  i++) {
       int b = pBuffer[pOffset++];
       if (b < 0) { b += 256; }
       num = (num << 8) + b;
       if (++numBytes == 3) {
         charBuffer[charOffset++] = intToBase64[num >> 18];
         charBuffer[charOffset++] = intToBase64[(num >> 12) & 0x3f];
         charBuffer[charOffset++] = intToBase64[(num >> 6) & 0x3f];
         charBuffer[charOffset++] = intToBase64[num & 0x3f];
         if (wrapSize > 0) {
           lineChars += 4;
           if (lineChars >= wrapSize) {
             wrap();
           }
         }
         num = 0;
         numBytes = 0;
         if (charOffset + skipChars > charBuffer.length) {
           writeBuffer(charBuffer, 0, charOffset);
           charOffset = 0;
         }
       }
     }
   }
   /** Writes any currently buffered data to the destination.
    * @throws IOException Invoking the {@link #writeBuffer(char[],int,int)}
    * method for writing the encoded data failed.
    */
   public void flush() throws IOException {
     if (numBytes > 0) {
       if (numBytes == 1) {
         charBuffer[charOffset++] = intToBase64[num >> 2];
         charBuffer[charOffset++] = intToBase64[(num << 4) & 0x3f];
         charBuffer[charOffset++] = "=";
         charBuffer[charOffset++] = "=";
       } else {
         charBuffer[charOffset++] = intToBase64[num >> 10];
         charBuffer[charOffset++] = intToBase64[(num >> 4) & 0x3f];
         charBuffer[charOffset++] = intToBase64[(num << 2) & 0x3f];
         charBuffer[charOffset++] = "=";
       }
       lineChars += 4;
       num = 0;
       numBytes = 0;
     }
     if (wrapSize > 0  &&  lineChars > 0) {
       wrap();
     }
     if (charOffset > 0) {
       writeBuffer(charBuffer, 0, charOffset);
       charOffset = 0;
     }
   }
 }
 /** An {@link OutputStream}, which is writing to the given
  * {@link Encoder}.
  */
 public static class EncoderOutputStream extends OutputStream {
   private final Encoder encoder;
   /** Creates a new instance, which is creating
    * output using the given {@link Encoder}.
    * @param pEncoder The base64 encoder being used.
    */
   public EncoderOutputStream(Encoder pEncoder) {
     encoder = pEncoder;
   }
   private final byte[] oneByte = new byte[1];
   public void write(int b) throws IOException {
     oneByte[0] = (byte) b;
     encoder.write(oneByte, 0, 1);
   }
   public void write(byte[] pBuffer, int pOffset, int pLen) throws IOException {
     encoder.write(pBuffer, pOffset, pLen);
   }
   public void close() throws IOException {
     encoder.flush();
   }
 }
 /** Returns an {@link OutputStream}, that encodes its input in Base64
  * and writes it to the given {@link Writer}. If the Base64 stream
  * ends, then the output streams {@link OutputStream#close()} method
  * must be invoked. Note, that this will not close the
  * target {@link Writer}!
  * @param pWriter Target writer.
  * @return An output stream, encoding its input in Base64 and writing
  * the output to the writer pWriter.
  */
 public static OutputStream newEncoder(Writer pWriter) {
   return newEncoder(pWriter, LINE_SIZE, LINE_SEPARATOR);
 }
 /** Returns an {@link OutputStream}, that encodes its input in Base64
  * and writes it to the given {@link Writer}. If the Base64 stream
  * ends, then the output streams {@link OutputStream#close()} method
  * must be invoked. Note, that this will not close the
  * target {@link Writer}!
  * @param pWriter Target writer.
  * @param pLineSize Size of one line in characters, must be a multiple
  * of four. Zero indicates, that no line wrapping should occur.
  * @param pSeparator Line separator or null, in which case the default value
  * {@link #LINE_SEPARATOR} is used.
  * @return An output stream, encoding its input in Base64 and writing
  * the output to the writer pWriter.
  */
 public static OutputStream newEncoder(final Writer pWriter, int pLineSize, String pSeparator) {
   final Encoder encoder = new Encoder(new char[4096], pLineSize, pSeparator){
     protected void writeBuffer(char[] pBuffer, int pOffset, int pLen) throws IOException {
       pWriter.write(pBuffer, pOffset, pLen);
     }
   };
   return new EncoderOutputStream(encoder);
 }
 /** An {@link Encoder}, which is writing to a SAX content handler.
  * This is typically used for embedding a base64 stream into an
  * XML document.
  */
 public static class SAXEncoder extends Encoder {
   private final ContentHandler handler;
   /** Creates a new instance.
    * @param pBuffer The encoders buffer.
    * @param pWrapSize A nonzero value indicates, that a line
    * wrap should be performed after the given number of
    * characters. The value must be a multiple of 4. Zero
    * indicates, that no line wrap should be performed.
    * @param pSep The eol sequence being used to terminate
    * a line in case of line wraps. May be null, in which
    * case the default value {@link Base64#LINE_SEPARATOR}
    * is being used.
    * @param pHandler The target handler.
    */
   public SAXEncoder(char[] pBuffer, int pWrapSize, String pSep,
             ContentHandler pHandler) {
     super(pBuffer, pWrapSize, pSep);
     handler = pHandler;
   }
   /** Writes to the content handler.
    * @throws SAXIOException Writing to the content handler
    * caused a SAXException.
    */
   protected void writeBuffer(char[] pChars, int pOffset, int pLen) throws IOException {
     try {
       handler.characters(pChars, pOffset, pLen);
     } catch (SAXException e) {
       throw new SAXIOException(e);
     }
   }
 }
 /** Converts the given byte array into a base64 encoded character
  * array.
  * @param pBuffer The buffer being encoded.
  * @param pOffset Offset in buffer, where to begin encoding.
  * @param pLength Number of bytes being encoded.
  * @return Character array of encoded bytes.
  */
 public static String encode(byte[] pBuffer, int pOffset, int pLength) {
   return encode(pBuffer, pOffset, pLength, LINE_SIZE, LINE_SEPARATOR);
 }
 /** Converts the given byte array into a base64 encoded character
  * array.
  * @param pBuffer The buffer being encoded.
  * @param pOffset Offset in buffer, where to begin encoding.
  * @param pLength Number of bytes being encoded.
  * @param pLineSize Size of one line in characters, must be a multiple
  * of four. Zero indicates, that no line wrapping should occur.
  * @param pSeparator Line separator or null, in which case the default value
  * {@link #LINE_SEPARATOR} is used.
  * @return Character array of encoded bytes.
  */
 public static String encode(byte[] pBuffer, int pOffset, int pLength,
               int pLineSize, String pSeparator) {
   StringWriter sw = new StringWriter();
   OutputStream ostream = newEncoder(sw, pLineSize, pSeparator);
   try {
     ostream.write(pBuffer, pOffset, pLength);
     ostream.close();
   } catch (IOException e) {
     throw new UndeclaredThrowableException(e);
   }
   return sw.toString();
 }
 /** Converts the given byte array into a base64 encoded character
  * array with the line size {@link #LINE_SIZE} and the separator
  * {@link #LINE_SEPARATOR}.
  * @param pBuffer The buffer being encoded.
  * @return Character array of encoded bytes.
  */
 public static String encode(byte[] pBuffer) {
   return encode(pBuffer, 0, pBuffer.length);
 }
 /** An encoder is an object, which is able to decode char arrays
  * in blocks of four bytes. Any such block is converted into a
  * array of three bytes.
  */
 public static abstract class Decoder {
   private final byte[] byteBuffer;
   private int byteBufferOffset;
   private int num, numBytes;
   private int eofBytes;
   /** Creates a new instance.
    * @param pBufLen The decoders buffer size. The decoder will
    * store up to this number of decoded bytes before invoking
    * {@link #writeBuffer(byte[],int,int)}.
    */
   protected Decoder(int pBufLen) {
     byteBuffer = new byte[pBufLen];
   }
   /** Called for writing the decoded bytes to the destination.
    * @param pBuffer The byte array being written.
    * @param pOffset Offset of the first byte being written.
    * @param pLen Number of bytes being written.
    * @throws IOException Writing to the destination failed.
    */
   protected abstract void writeBuffer(byte[] pBuffer, int pOffset, int pLen) throws IOException;
   /** Converts the Base64 encoded character array.
    * @param pData The character array being decoded.
    * @param pOffset Offset of first character being decoded.
    * @param pLen Number of characters being decoded.
    * @throws DecodingException Decoding failed.
    * @throws IOException An invocation of the {@link #writeBuffer(byte[],int,int)}
    * method failed.
    */
   public void write(char[] pData, int pOffset, int pLen) throws IOException {
     for (int i = 0;  i < pLen;  i++) {
       char c = pData[pOffset++];
       if (Character.isWhitespace(c)) {
         continue;
       }
       if (c == "=") {
         ++eofBytes;
         num = num << 6;
         switch(++numBytes) {
           case 1:
           case 2:
             throw new DecodingException("Unexpected end of stream character (=)");
           case 3:
             // Wait for the next "="
             break;
           case 4:
             byteBuffer[byteBufferOffset++] = (byte) (num >> 16);
             if (eofBytes == 1) {
               byteBuffer[byteBufferOffset++] = (byte) (num >> 8);
             }
             writeBuffer(byteBuffer, 0, byteBufferOffset);
             byteBufferOffset = 0;
             break;
           case 5:
             throw new DecodingException("Trailing garbage detected");
           default:
             throw new IllegalStateException("Invalid value for numBytes");
         }
       } else {
         if (eofBytes > 0) {
           throw new DecodingException("Base64 characters after end of stream character (=) detected.");
         }
         int result;
         if (c >= 0  &&  c < base64ToInt.length) {
           result = base64ToInt[c];
           if (result >= 0) {
             num = (num << 6) + result;
             if (++numBytes == 4) {
               byteBuffer[byteBufferOffset++] = (byte) (num >> 16);
               byteBuffer[byteBufferOffset++] = (byte) ((num >> 8) & 0xff);
               byteBuffer[byteBufferOffset++] = (byte) (num & 0xff);
               if (byteBufferOffset + 3 > byteBuffer.length) {
                 writeBuffer(byteBuffer, 0, byteBufferOffset);
                 byteBufferOffset = 0;
               }
               num = 0;
               numBytes = 0;
             }
             continue;
           }
           }
         if (!Character.isWhitespace(c)) {
           throw new DecodingException("Invalid Base64 character: " + (int) c);
         }
       }
     }
   }
   /** Indicates, that no more data is being expected. Writes all currently
    * buffered data to the destination by invoking {@link #writeBuffer(byte[],int,int)}.
    * @throws DecodingException Decoding failed (Unexpected end of file).
    * @throws IOException An invocation of the {@link #writeBuffer(byte[],int,int)} method failed.
    */
   public void flush() throws IOException {
     if (numBytes != 0  &&  numBytes != 4) {
       throw new DecodingException("Unexpected end of file");
     }
     if (byteBufferOffset > 0) {
       writeBuffer(byteBuffer, 0, byteBufferOffset);
       byteBufferOffset = 0;
     }
   }
 }
 /** Returns a {@link Writer}, that decodes its Base64 encoded
  * input and writes it to the given {@link OutputStream}.
  * Note, that the writers {@link Writer#close()} method will
  * not close the output stream pStream!
  * @param pStream Target output stream.
  * @return An output stream, encoding its input in Base64 and writing
  * the output to the writer pWriter.
  */
 public Writer newDecoder(final OutputStream pStream) {
   return new Writer(){
     private final Decoder decoder = new Decoder(1024){
       protected void writeBuffer(byte[] pBytes, int pOffset, int pLen) throws IOException {
         pStream.write(pBytes, pOffset, pLen);
       }
     };
     public void close() throws IOException {
       flush();
     }
     public void flush() throws IOException {
       decoder.flush();
       pStream.flush();
     }
     public void write(char[] cbuf, int off, int len) throws IOException {
       decoder.write(cbuf, off, len);
     }
   };
 }
 /** Converts the given base64 encoded character buffer into a byte array.
  * @param pBuffer The character buffer being decoded.
  * @param pOffset Offset of first character being decoded.
  * @param pLength Number of characters being decoded.
  * @return Converted byte array
  * @throws DecodingException The input character stream contained invalid data.
  */
 public static byte[] decode(char[] pBuffer, int pOffset, int pLength) throws DecodingException {
   final ByteArrayOutputStream baos = new ByteArrayOutputStream();
   Decoder d = new Decoder(1024){
     protected void writeBuffer(byte[] pBuf, int pOff, int pLen) throws IOException {
       baos.write(pBuf, pOff, pLen);
     }
   };
   try {
     d.write(pBuffer, pOffset, pLength);
     d.flush();
   } catch (DecodingException e) {
     throw e;
   } catch (IOException e) {
     throw new UndeclaredThrowableException(e);
   }
   return baos.toByteArray();
 }
 /** Converts the given base64 encoded character buffer into a byte array.
  * @param pBuffer The character buffer being decoded.
  * @return Converted byte array
  * @throws DecodingException The input character stream contained invalid data.
  */
 public static byte[] decode(char[] pBuffer) throws DecodingException {
   return decode(pBuffer, 0, pBuffer.length);
 }
 /** Converts the given base64 encoded String into a byte array.
  * @param pBuffer The string being decoded.
  * @return Converted byte array
  * @throws DecodingException The input character stream contained invalid data.
  */
 public static byte[] decode(String pBuffer) throws DecodingException {
   return decode(pBuffer.toCharArray());
 }

}



 </source>
   
  
 
  



Provides Base64 encoding and decoding as defined by RFC 2045

   <source lang="java">
   

/*

* $Id: Base64.java 460331 2006-04-18 22:03:12Z dashorst $
* $Revision: 460331 $ $Date: 2006-04-19 00:03:12 +0200 (Wed, 19 Apr 2006) $
*
* 
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/

/**

* Provides Base64 encoding and decoding as defined by RFC 2045.
* <p/>
* This class is taken from the Apache commons-codec, and adjusted to fit the
* Wicket framework"s needs, especially external dependencies have been removed.
*

* <p/>
* This class implements section 6.8. Base64 Content-Transfer-Encoding
* from RFC 2045 Multipurpose Internet Mail Extensions (MIME) Part One:
* Format of Internet Message Bodies by Freed and Borenstein.</p>
*
* @author Apache Software Foundation
* @since 1.2
*/

public class Base64 {

   /**
    * Chunk size per RFC 2045 section 6.8.
    * <p/>
*

The {@value} character limit does not count the trailing CRLF, but counts * all other characters, including any equal signs.

    *
    * @see 
    */
   static final byte[] CHUNK_SEPARATOR = "\r\n".getBytes();
   /**
    * The base length.
    */
   static final int BASELENGTH = 255;
   /**
    * Lookup length.
    */
   static final int LOOKUPLENGTH = 64;
   /**
    * Used to calculate the number of bits in a byte.
    */
   static final int EIGHTBIT = 8;
   /**
    * Used when encoding something which has fewer than 24 bits.
    */
   static final int SIXTEENBIT = 16;
   /**
    * Used to determine how many bits data contains.
    */
   static final int TWENTYFOURBITGROUP = 24;
   /**
    * Used to get the number of Quadruples.
    */
   static final int FOURBYTE = 4;
   /**
    * Used to test the sign of a byte.
    */
   static final int SIGN = -128;
   /**
    * Byte used to pad output.
    */
   static final byte PAD = (byte) "=";
   /**
    * Contains the Base64 values 0 through 63 accessed by using character encodings as
    * indices.
    * <p/>
    * For example, base64Alphabet["+"] returns 62.
    * </p>
    * <p/>
    * The value of undefined encodings is -1.
    * </p>
    */
   private static byte[] base64Alphabet = new byte[BASELENGTH];
   /**
    * <p/>
    * Contains the Base64 encodings A through Z, followed by a through
    * z, followed by 0 through 9, followed by +, and
    * /.
    * </p>
    * <p/>
    * This array is accessed by using character values as indices.
    * </p>
    * <p/>
    * For example, lookUpBase64Alphabet[62]  returns "+".
    * </p>
    */
   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 <= 25; i++)
       {
           lookUpBase64Alphabet[i] = (byte) ("A" + i);
       }
       for (int i = 26, j = 0; i <= 51; i++, j++)
       {
           lookUpBase64Alphabet[i] = (byte) ("a" + j);
       }
       for (int i = 52, j = 0; i <= 61; i++, j++)
       {
           lookUpBase64Alphabet[i] = (byte) ("0" + j);
       }
       lookUpBase64Alphabet[62] = (byte) "+";
       lookUpBase64Alphabet[63] = (byte) "/";
   }
   /**
    * Returns whether or not the octect is in the base 64 alphabet.
    *
    * @param octect The value to test
    * @return true if the value is defined in the the base 64 alphabet, false otherwise.
    */
   private static boolean isBase64(byte octect)
   {
       if (octect == PAD)
       {
           return true;
       }
       else if (octect < 0 || base64Alphabet[octect] == -1)
       {
           return false;
       }
       else
       {
           return true;
       }
   }
   /**
    * Tests a given byte array to see if it contains
    * only valid characters within the Base64 alphabet.
    *
    * @param arrayOctect byte array to test
    * @return true if all bytes are valid characters in the Base64
    *         alphabet or if the byte array is empty; false, otherwise
    */
   public static boolean isArrayByteBase64(byte[] arrayOctect)
   {
       arrayOctect = discardWhitespace(arrayOctect);
       int length = arrayOctect.length;
       if (length == 0)
       {
           // shouldn"t a 0 length array be valid base64 data?
           // return false;
           return true;
       }
       for (int i = 0; i < length; i++)
       {
           if (!isBase64(arrayOctect[i]))
           {
               return false;
           }
       }
       return true;
   }
   /**
    * Encodes binary data using the base64 algorithm but
    * does not chunk the output.
    *
    * @param binaryData binary data to encode
    * @return Base64 characters
    */
   public static byte[] encodeBase64(byte[] binaryData)
   {
       return encodeBase64(binaryData, false);
   }
   /**
    * Encodes binary data using the base64 algorithm and chunks
    * the encoded output into 76 character blocks
    *
    * @param binaryData binary data to encode
    * @return Base64 characters chunked in 76 character blocks
    */
   public static byte[] encodeBase64Chunked(byte[] binaryData)
   {
       return encodeBase64(binaryData, true);
   }
   /**
    * Decodes an Object using the base64 algorithm.  This method
    * is provided in order to satisfy the requirements of the
    * Decoder interface, and will throw a DecoderException if the
    * supplied object is not of type byte[].
    *
    * @param pObject Object to decode
    * @return An object (of type byte[]) containing the
    *         binary data which corresponds to the byte[] supplied.
    * @throws IllegalArgumentException if the parameter supplied is not
    *                                  of type byte[]
    */
   public Object decode(Object pObject)
   {
       if (!(pObject instanceof byte[]))
       {
           throw new IllegalArgumentException("Parameter supplied to Base64 decode is not a byte[]");
       }
       return decode((byte[]) pObject);
   }
   /**
    * Decodes a byte[] containing containing
    * characters in the Base64 alphabet.
    *
    * @param pArray A byte array containing Base64 character data
    * @return a byte array containing binary data
    */
   public byte[] decode(byte[] pArray)
   {
       return decodeBase64(pArray);
   }
   /**
    * Encodes binary data using the base64 algorithm, optionally
    * chunking the output into 76 character blocks.
    *
    * @param binaryData Array containing binary data to encode.
    * @param isChunked  if true this encoder will chunk
    *                   the base64 output into 76 character blocks
    * @return Base64-encoded data.
    */
   public static byte[] encodeBase64(byte[] binaryData, boolean isChunked)
   {
       int lengthDataBits = binaryData.length * EIGHTBIT;
       int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
       int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
       byte encodedData[] = null;
       int encodedDataLength = 0;
       int nbrChunks = 0;
       if (fewerThan24bits != 0)
       {
           //data not divisible by 24 bit
           encodedDataLength = (numberTriplets + 1) * 4;
       }
       else
       {
           // 16 or 8 bit
           encodedDataLength = numberTriplets * 4;
       }
       // If the output is to be "chunked" into 76 character sections, 
       // for compliance with RFC 2045 MIME, then it is important to 
       // allow for extra length to account for the separator(s)
       if (isChunked)
       {
           nbrChunks =
                   (CHUNK_SEPARATOR.length == 0 ? 0 : (int) Math.ceil((float) encodedDataLength / CHUNK_SIZE));
           encodedDataLength += nbrChunks * CHUNK_SEPARATOR.length;
       }
       encodedData = new byte[encodedDataLength];
       byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
       int encodedIndex = 0;
       int dataIndex = 0;
       int i = 0;
       int nextSeparatorIndex = CHUNK_SIZE;
       int chunksSoFar = 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);
           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);
           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];
           encodedIndex += 4;
           // If we are chunking, let"s put a chunk separator down.
           if (isChunked)
           {
               // this assumes that CHUNK_SIZE % 4 == 0
               if (encodedIndex == nextSeparatorIndex)
               {
                   System.arraycopy(
                           CHUNK_SEPARATOR,
                           0,
                           encodedData,
                           encodedIndex,
                           CHUNK_SEPARATOR.length);
                   chunksSoFar++;
                   nextSeparatorIndex =
                           (CHUNK_SIZE * (chunksSoFar + 1)) +
                                   (chunksSoFar * CHUNK_SEPARATOR.length);
                   encodedIndex += CHUNK_SEPARATOR.length;
               }
           }
       }
       // form integral number of 6-bit groups
       dataIndex = i * 3;
       if (fewerThan24bits == EIGHTBIT)
       {
           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 == 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 + 1] =
                   lookUpBase64Alphabet[val2 | (k << 4)];
           encodedData[encodedIndex + 2] = lookUpBase64Alphabet[l << 2];
           encodedData[encodedIndex + 3] = PAD;
       }
       if (isChunked)
       {
           // we also add a separator to the end of the final chunk.
           if (chunksSoFar < nbrChunks)
           {
               System.arraycopy(
                       CHUNK_SEPARATOR,
                       0,
                       encodedData,
                       encodedDataLength - CHUNK_SEPARATOR.length,
                       CHUNK_SEPARATOR.length);
           }
       }
       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)
   {
       // RFC 2045 requires that we discard ALL non-Base64 characters
       base64Data = discardNonBase64(base64Data);
       // handle the edge case, so we don"t have to worry about it later
       if (base64Data.length == 0)
       {
           return new byte[0];
       }
       int numberQuadruple = base64Data.length / FOURBYTE;
       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)
           {
               //Two 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;
   }
   /**
    * Discards any whitespace from a base-64 encoded block.
    *
    * @param data The base-64 encoded data to discard the whitespace
    *             from.
    * @return The data, less whitespace (see RFC 2045).
    */
   static byte[] discardWhitespace(byte[] data)
   {
       byte groomedData[] = new byte[data.length];
       int bytesCopied = 0;
       for (int i = 0; i < data.length; i++)
       {
           switch (data[i])
           {
               case (byte) " " :
               case (byte) "\n" :
               case (byte) "\r" :
               case (byte) "\t" :
                   break;
               default:
                   groomedData[bytesCopied++] = data[i];
           }
       }
       byte packedData[] = new byte[bytesCopied];
       System.arraycopy(groomedData, 0, packedData, 0, bytesCopied);
       return packedData;
   }
   /**
    * Discards any characters outside of the base64 alphabet, per
    * the requirements on page 25 of RFC 2045 - "Any characters
    * outside of the base64 alphabet are to be ignored in base64
    * encoded data."
    *
    * @param data The base-64 encoded data to groom
    * @return The data, less non-base64 characters (see RFC 2045).
    */
   static byte[] discardNonBase64(byte[] data)
   {
       byte groomedData[] = new byte[data.length];
       int bytesCopied = 0;
       for (int i = 0; i < data.length; i++)
       {
           if (isBase64(data[i]))
           {
               groomedData[bytesCopied++] = data[i];
           }
       }
       byte packedData[] = new byte[bytesCopied];
       System.arraycopy(groomedData, 0, packedData, 0, bytesCopied);
       return packedData;
   }
   // Implementation of the Encoder Interface
   /**
    * Encodes an Object using the base64 algorithm.  This method
    * is provided in order to satisfy the requirements of the
    * Encoder interface, and will throw an EncoderException if the
    * supplied object is not of type byte[].
    *
    * @param pObject Object to encode
    * @return An object (of type byte[]) containing the
    *         base64 encoded data which corresponds to the byte[] supplied.
    * @throws IllegalArgumentException if the parameter supplied is not
    *                                  of type byte[]
    */
   public Object encode(Object pObject)
   {
       if (!(pObject instanceof byte[]))
       {
           throw new IllegalArgumentException(
                   "Parameter supplied to Base64 encode is not a byte[]");
       }
       return encode((byte[]) pObject);
   }
   /**
    * Encodes a byte[] containing binary data, into a byte[] containing
    * characters in the Base64 alphabet.
    *
    * @param pArray a byte array containing binary data
    * @return A byte array containing only Base64 character data
    */
   public byte[] encode(byte[] pArray)
   {
       return encodeBase64(pArray, false);
   }

}



 </source>
   
  
 
  



Provides Base64 encoding and decoding with URL and filename safe alphabet as defined by RFC 3548, section 4.

   <source lang="java">
   

/*

* $Id: Base64.java 5325 2006-04-10 20:56:57 +0000 (Mon, 10 Apr 2006) jdonnerstag $
* $Revision: 5325 $ $Date: 2006-04-10 20:56:57 +0000 (Mon, 10 Apr 2006) $
*
* 
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/

/**

* Provides Base64 encoding and decoding with URL and filename safe alphabet
* as defined by RFC 3548, section 4.
* <p/>
* This Base64 encoder is modified to meet URL requirements. The changes are:
* "+" => "*", 
* "/" => "-", 
* and no padding.
* <p/>
* This class is taken from the Apache commons-codec, and adjusted to fit the
* Wicket framework"s needs, especially external dependencies have been removed.
* </p>
* <p/>
* This class implements section 4. Base 64 Encoding with URL and Filename Safe Alphabet
* from RFC 3548 The Base16, Base32, and Base64 Data Encodings by Simon Josefsson.</p>
*
* @author Apache Software Foundation
* @author Juergen Donnerstag
* 
* @since 1.2
*/

public class Base64UrlSafe {

   /**
    * The base length.
    */
   static final int BASELENGTH = 255;
   /**
    * Lookup length.
    */
   static final int LOOKUPLENGTH = 64;
   /**
    * Used to calculate the number of bits in a byte.
    */
   static final int EIGHTBIT = 8;
   /**
    * Used when encoding something which has fewer than 24 bits.
    */
   static final int SIXTEENBIT = 16;
   /**
    * Used to determine how many bits data contains.
    */
   static final int TWENTYFOURBITGROUP = 24;
   /**
    * Used to get the number of Quadruples.
    */
   static final int FOURBYTE = 4;
   /**
    * Used to test the sign of a byte.
    */
   static final int SIGN = -128;
   /**
    * Contains the Base64 values 0 through 63 accessed by using character encodings as
    * indices.
    * <p/>
    * For example, base64Alphabet["+"] returns 62.
    * </p>
    * <p/>
    * The value of undefined encodings is -1.
    * </p>
    */
   private static byte[] base64Alphabet = new byte[BASELENGTH];
   /**
    * <p/>
    * Contains the Base64 encodings A through Z, followed by a through
    * z, followed by 0 through 9, followed by +, and
    * /.
    * </p>
    * <p/>
    * This array is accessed by using character values as indices.
    * </p>
    * <p/>
    * For example, lookUpBase64Alphabet[62]  returns "+".
    * </p>
    */
   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 <= 25; i++)
       {
           lookUpBase64Alphabet[i] = (byte) ("A" + i);
       }
       for (int i = 26, j = 0; i <= 51; i++, j++)
       {
           lookUpBase64Alphabet[i] = (byte) ("a" + j);
       }
       for (int i = 52, j = 0; i <= 61; i++, j++)
       {
           lookUpBase64Alphabet[i] = (byte) ("0" + j);
       }
       lookUpBase64Alphabet[62] = (byte) "*";
       lookUpBase64Alphabet[63] = (byte) "-";
   }
   /**
    * Returns whether or not the octect is in the base 64 alphabet.
    *
    * @param octect The value to test
    * @return true if the value is defined in the the base 64 alphabet, false otherwise.
    */
   private static boolean isBase64(byte octect)
   {
       if (octect < 0 || base64Alphabet[octect] == -1)
       {
           return false;
       }
       else
       {
           return true;
       }
   }
   /**
    * Tests a given byte array to see if it contains
    * only valid characters within the Base64 alphabet.
    *
    * @param arrayOctect byte array to test
    * @return true if all bytes are valid characters in the Base64
    *         alphabet or if the byte array is empty; false, otherwise
    */
   public static boolean isArrayByteBase64(byte[] arrayOctect)
   {
       arrayOctect = discardWhitespace(arrayOctect);
       int length = arrayOctect.length;
       if (length == 0)
       {
           // shouldn"t a 0 length array be valid base64 data?
           // return false;
           return true;
       }
       for (int i = 0; i < length; i++)
       {
           if (!isBase64(arrayOctect[i]))
           {
               return false;
           }
       }
       return true;
   }
   /**
    * Decodes an Object using the base64 algorithm.  This method
    * is provided in order to satisfy the requirements of the
    * Decoder interface, and will throw a DecoderException if the
    * supplied object is not of type byte[].
    *
    * @param pObject Object to decode
    * @return An object (of type byte[]) containing the
    *         binary data which corresponds to the byte[] supplied.
    * @throws IllegalArgumentException if the parameter supplied is not
    *                                  of type byte[]
    */
   public Object decode(Object pObject)
   {
       if (!(pObject instanceof byte[]))
       {
           throw new IllegalArgumentException("Parameter supplied to Base64 decode is not a byte[]");
       }
       return decode((byte[]) pObject);
   }
   /**
    * Decodes a byte[] containing containing
    * characters in the Base64 alphabet.
    *
    * @param pArray A byte array containing Base64 character data
    * @return a byte array containing binary data
    */
   public byte[] decode(byte[] pArray)
   {
       return decodeBase64(pArray);
   }
   /**
    * Encodes binary data using the base64 algorithm.
    *
    * @param binaryData Array containing binary data to encode.
    * @return Base64-encoded data.
    */
   public static byte[] encodeBase64(byte[] binaryData)
   {
       int lengthDataBits = binaryData.length * EIGHTBIT;
       int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
       int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
       byte encodedData[] = null;
       int encodedDataLength = 0;
       if (fewerThan24bits != 0)
       {
           //data not divisible by 24 bit
           encodedDataLength = (numberTriplets + 1) * 4;
       }
       else
       {
           // 16 or 8 bit
           encodedDataLength = numberTriplets * 4;
       }
       if (fewerThan24bits == EIGHTBIT)
       {
         encodedDataLength -= 2;
       }
       else if (fewerThan24bits == SIXTEENBIT)
       {
         encodedDataLength -= 1;
       }
       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);
           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);
           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];
           encodedIndex += 4;
       }
       // form integral number of 6-bit groups
       dataIndex = i * 3;
       if (fewerThan24bits == EIGHTBIT)
       {
           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];
       }
       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 + 1] =
                   lookUpBase64Alphabet[val2 | (k << 4)];
           encodedData[encodedIndex + 2] = lookUpBase64Alphabet[l << 2];
       }
       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)
   {
       // RFC 2045 requires that we discard ALL non-Base64 characters
       base64Data = discardNonBase64(base64Data);
       // handle the edge case, so we don"t have to worry about it later
       if (base64Data.length == 0)
       {
           return new byte[0];
       }
       int numberQuadruple = (base64Data.length + 3) / FOURBYTE;
       byte decodedData[] = new byte[base64Data.length - numberQuadruple];
       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;
       for (int i = 0; i < numberQuadruple; i++)
       {
           dataIndex = i * 4;
           b1 = base64Alphabet[base64Data[dataIndex]];
           b2 = base64Alphabet[base64Data[dataIndex + 1]];
           if ((dataIndex + 3) < base64Data.length)
           {
               //No PAD e.g 3cQl
               b3 = base64Alphabet[base64Data[dataIndex + 2]];
               b4 = base64Alphabet[base64Data[dataIndex + 3]];
               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 ((dataIndex + 2) < base64Data.length)
           {
               //One PAD e.g. 3cQ[Pad]
               b3 = base64Alphabet[base64Data[dataIndex + 2]];
               decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
               decodedData[encodedIndex + 1] =
                       (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
           }
           else if ((dataIndex + 1) < base64Data.length)
           {
               //Two PAD e.g. 3c[Pad][Pad]
               decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
           }
           encodedIndex += 3;
       }
       return decodedData;
   }
   /**
    * Discards any whitespace from a base-64 encoded block.
    *
    * @param data The base-64 encoded data to discard the whitespace
    *             from.
    * @return The data, less whitespace (see RFC 2045).
    */
   static byte[] discardWhitespace(byte[] data)
   {
       byte groomedData[] = new byte[data.length];
       int bytesCopied = 0;
       for (int i = 0; i < data.length; i++)
       {
           switch (data[i])
           {
               case (byte) " " :
               case (byte) "\n" :
               case (byte) "\r" :
               case (byte) "\t" :
                   break;
               default:
                   groomedData[bytesCopied++] = data[i];
           }
       }
       byte packedData[] = new byte[bytesCopied];
       System.arraycopy(groomedData, 0, packedData, 0, bytesCopied);
       return packedData;
   }
   /**
    * Discards any characters outside of the base64 alphabet, per
    * the requirements on page 25 of RFC 2045 - "Any characters
    * outside of the base64 alphabet are to be ignored in base64
    * encoded data."
    *
    * @param data The base-64 encoded data to groom
    * @return The data, less non-base64 characters (see RFC 2045).
    */
   static byte[] discardNonBase64(byte[] data)
   {
       byte groomedData[] = new byte[data.length];
       int bytesCopied = 0;
       for (int i = 0; i < data.length; i++)
       {
           if (isBase64(data[i]))
           {
               groomedData[bytesCopied++] = data[i];
           }
       }
       byte packedData[] = new byte[bytesCopied];
       System.arraycopy(groomedData, 0, packedData, 0, bytesCopied);
       return packedData;
   }
   // Implementation of the Encoder Interface
   /**
    * Encodes an Object using the base64 algorithm.  This method
    * is provided in order to satisfy the requirements of the
    * Encoder interface, and will throw an EncoderException if the
    * supplied object is not of type byte[].
    *
    * @param pObject Object to encode
    * @return An object (of type byte[]) containing the
    *         base64 encoded data which corresponds to the byte[] supplied.
    * @throws IllegalArgumentException if the parameter supplied is not
    *                                  of type byte[]
    */
   public Object encode(Object pObject)
   {
       if (!(pObject instanceof byte[]))
       {
           throw new IllegalArgumentException(
                   "Parameter supplied to Base64 encode is not a byte[]");
       }
       return encode((byte[]) pObject);
   }
   /**
    * Encodes a byte[] containing binary data, into a byte[] containing
    * characters in the Base64 alphabet.
    *
    * @param pArray a byte array containing binary data
    * @return A byte array containing only Base64 character data
    */
   public byte[] encode(byte[] pArray)
   {
       return encodeBase64(pArray);
   }

}



 </source>
   
  
 
  



Provides utility methods to Base64 encode data

   <source lang="java">
   

/*

*
* 
* Copyright 2005 Vincent Massol.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* 
*   http://www.apache.org/licenses/LICENSE-2.0
* 
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* 
* 
*/

import java.io.ByteArrayOutputStream; /**

* Provides utility methods to Base64 encode data. This class uses the Base64 encoding as specified
* in RFC 2045, 6.8. Base64 Content-Transfer-Encoding.
* 
* @version $Id: Base64.java 1705 2008-09-02 13:14:55Z adriana $
*/

public final class Base64 {

   // constants --------------------------------------------------------------
   /**
    * The Base64 character set look-up table. This consists of the following ordered alphanumerics:
    * A-Z, a-z, 0-9, + and /.
    */
   private static final char[] ENCODE = new char[64];
   /**
    * The character to pad the output with if not a multiple of 24-bits.
    */
   private static final char PAD_CHAR = "=";
   // static -----------------------------------------------------------------
   static
   {
       // create Base64 character look-up table
       for (int i = 0; i < 26; i++)
       {
           ENCODE[i] = (char) ("A" + i);
           ENCODE[i + 26] = (char) ("a" + i);
       }
       for (int i = 0; i < 10; i++)
       {
           ENCODE[i + 52] = (char) ("0" + i);
       }
       ENCODE[62] = "+";
       ENCODE[63] = "/";
   }
   // constructors -----------------------------------------------------------
   /**
    * Private to prevent unnecessary instantation.
    */
   private Base64()
   {
       // Private to prevent unnecessary instantation
   }
   // public methods ---------------------------------------------------------
   /**
    * Base64 encodes the specified bytes. This method is provided for signature compatibility with
    * commons-codec.
    * 
    * @param bytes the bytes to encode
    * @return the encoded bytes
    */
   public static byte[] encodeBase64(byte[] bytes)
   {
       return encode(bytes);
   }
   /**
    * Base64 encodes the specified string using the platform"s default encoding.
    * 
    * @param string the string to encode
    * @return the encoded string
    */
   public static String encode(String string)
   {
       return new String(encode(string.getBytes()));
   }
   /**
    * Base64 encodes the specified bytes.
    * 
    * @param bytes the bytes to encode
    * @return the encoded bytes
    */
   public static byte[] encode(byte[] bytes)
   {
       ByteArrayOutputStream out = new ByteArrayOutputStream();
       int count = 0;
       int carry = 0;
       for (int i = 0; i < bytes.length; i++)
       {
           byte b = bytes[i];
           switch (count++ % 3)
           {
               // first byte of 24-bits: write 6-bits and carry 2-bits
               case 0:
                   out.write(ENCODE[b >> 2]);
                   carry = b & 0x03;
                   break;
               // second byte of 24-bits: write carry + 4-bits, carry 4-bits
               case 1:
                   out.write(ENCODE[(carry << 4) + (b >> 4)]);
                   carry = b & 0x0F;
                   break;
               // third byte of 24-bits: write carry + 2-bits, write 6-bits
               case 2:
                   out.write(ENCODE[(carry << 2) + (b >> 6)]);
                   out.write(ENCODE[b & 0x3F]);
                   break;
               default:
                   throw new InternalError();
           }
       }
       switch (count % 3)
       {
           // third byte of 24-bits: 24-bit aligned
           case 0:
               break;
           // first byte of 24-bits: write 4-bit carry and pad 16-bits
           case 1:
               out.write(ENCODE[carry << 4]);
               out.write(PAD_CHAR);
               out.write(PAD_CHAR);
               break;
           // second byte of 24-bits: write 2-bit carry and pad 8-bits
           case 2:
               out.write(ENCODE[carry << 2]);
               out.write(PAD_CHAR);
               break;
           default:
               throw new InternalError();
       }
       return out.toByteArray();
   }

}



 </source>
   
  
 
  



QP Decoder Stream

   <source lang="java">
   

/*

* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License").  You
* may not use this file except in compliance with the License. You can obtain
* a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code.  If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [year]
* [name of copyright owner]"
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license."  If you don"t indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above.  However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/

/*

* @(#)QPDecoderStream.java 1.11 07/05/04
*/

import java.io.*; /**

* This class implements a QP Decoder. It is implemented as
* a FilterInputStream, so one can just wrap this class around
* any input stream and read bytes from this filter. The decoding
* is done as the bytes are read out.
* 
* @author John Mani
*/

public class QPDecoderStream extends FilterInputStream {

   protected byte[] ba = new byte[2];
   protected int spaces = 0;
   /**
    * Create a Quoted Printable decoder that decodes the specified 
    * input stream.
    * @param in        the input stream
    */
   public QPDecoderStream(InputStream in) {
 super(new PushbackInputStream(in, 2)); // pushback of size=2
   }
   /**
    * Read the next decoded byte from this input stream. The byte
    * is returned as an int in the range 0
    * to 255. If no byte is available because the end of
    * the stream has been reached, the value -1 is returned.
    * This method blocks until input data is available, the end of the
    * stream is detected, or an exception is thrown.
    *
    * @return     the next byte of data, or -1 if the end of the
    *             stream is reached.
    * @exception  IOException  if an I/O error occurs.
    */
   public int read() throws IOException {
 if (spaces > 0) {
     // We have cached space characters, return one
     spaces--;
     return " ";
 }
 
 int c = in.read();
 if (c == " ") { 
     // Got space, keep reading till we get a non-space char
     while ((c = in.read()) == " ")
   spaces++;
     if (c == "\r" || c == "\n" || c == -1)
   // If the non-space char is CR/LF/EOF, the spaces we got
       // so far is junk introduced during transport. Junk "em.
   spaces = 0;
         else {
   // The non-space char is NOT CR/LF, the spaces are valid.
   ((PushbackInputStream)in).unread(c);
   c = " ";
     }
     return c; // return either <SPACE> or <CR/LF>
 }
 else if (c == "=") {
     // QP Encoded atom. Decode the next two bytes
     int a = in.read();
     if (a == "\n") {
   /* Hmm ... not really confirming QP encoding, but lets
    * allow this as a LF terminated encoded line .. and
    * consider this a soft linebreak and recurse to fetch 
    * the next char.
    */
   return read();
     } else if (a == "\r") {
   // Expecting LF. This forms a soft linebreak to be ignored.
   int b = in.read();
   if (b != "\n") 
       /* Not really confirming QP encoding, but
        * lets allow this as well.
        */
       ((PushbackInputStream)in).unread(b);
   return read();
     } else if (a == -1) {
     // Not valid QP encoding, but we be nice and tolerant here !
   return -1;
     } else {
   ba[0] = (byte)a;
   ba[1] = (byte)in.read();
   try {
       return ASCIIUtility.parseInt(ba, 0, 2, 16);
   } catch (NumberFormatException nex) {
       /*
       System.err.println(
         "Illegal characters in QP encoded stream: " + 
         ASCIIUtility.toString(ba, 0, 2)
       );
       */
       ((PushbackInputStream)in).unread(ba);
       return c;
   }
     }
 }
 return c;
   }
   /**
    * Reads up to len decoded bytes of data from this input stream
    * into an array of bytes. This method blocks until some input is
    * available.
*

* * @param buf the buffer into which the data is read. * @param off the start offset of the data. * @param len the maximum number of bytes read. * @return the total number of bytes read into the buffer, or * -1 if there is no more data because the end of * the stream has been reached. * @exception IOException if an I/O error occurs. */ public int read(byte[] buf, int off, int len) throws IOException { int i, c; for (i = 0; i < len; i++) { if ((c = read()) == -1) { if (i == 0) // At end of stream, so we should i = -1; // return -1 , NOT 0. break; } buf[off+i] = (byte)c; } return i; } /** * Tests if this input stream supports marks. Currently this class * does not support marks */ public boolean markSupported() { return false; } /** * Returns the number of bytes that can be read from this input * stream without blocking. The QP algorithm does not permit * a priori knowledge of the number of bytes after decoding, so * this method just invokes the available method * of the original input stream. */ public int available() throws IOException { // This is bogus ! We don"t really know how much // bytes are available *after* decoding return in.available(); } /**** begin TEST program public static void main(String argv[]) throws Exception { FileInputStream infile = new FileInputStream(argv[0]); QPDecoderStream decoder = new QPDecoderStream(infile); int c; while ((c = decoder.read()) != -1) System.out.print((char)c); System.out.println(); } *** end TEST program ****/ } /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development * and Distribution License("CDDL") (collectively, the "License"). You * may not use this file except in compliance with the License. You can obtain * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific * language governing permissions and limitations under the License. * * When distributing the software, include this License Header Notice in each * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt. * Sun designates this particular file as subject to the "Classpath" exception * as provided by Sun in the GPL Version 2 section of the License file that * accompanied this code. If applicable, add the following below the License * Header, with the fields enclosed by brackets [] replaced by your own * identifying information: "Portions Copyrighted [year] * [name of copyright owner]" * * Contributor(s): * * If you wish your version of this file to be governed by only the CDDL or * only the GPL Version 2, indicate your decision by adding "[Contributor] * elects to include this software in this distribution under the [CDDL or GPL * Version 2] license." If you don"t indicate a single choice of license, a * recipient has the option to distribute your version of this file under * either the CDDL, the GPL Version 2 or to extend the choice of license to * its licensees as provided above. However, if you add GPL Version 2 code * and therefore, elected the GPL Version 2 license, then the option applies * only if the new code is made subject to such option by the copyright * holder. */ /* * @(#)ASCIIUtility.java 1.11 07/05/04 */ class ASCIIUtility { // Private constructor so that this class is not instantiated private ASCIIUtility() { } /** * Convert the bytes within the specified range of the given byte * array into a signed integer in the given radix . The range extends * from start till, but not including end. <p> * * Based on java.lang.Integer.parseInt() */ public static int parseInt(byte[] b, int start, int end, int radix) throws NumberFormatException { if (b == null) throw new NumberFormatException("null"); int result = 0; boolean negative = false; int i = start; int limit; int multmin; int digit; if (end > start) { if (b[i] == "-") { negative = true; limit = Integer.MIN_VALUE; i++; } else { limit = -Integer.MAX_VALUE; } multmin = limit / radix; if (i < end) { digit = Character.digit((char)b[i++], radix); if (digit < 0) { throw new NumberFormatException( "illegal number: " + toString(b, start, end) ); } else { result = -digit; } } while (i < end) { // Accumulating negatively avoids surprises near MAX_VALUE digit = Character.digit((char)b[i++], radix); if (digit < 0) { throw new NumberFormatException("illegal number"); } if (result < multmin) { throw new NumberFormatException("illegal number"); } result *= radix; if (result < limit + digit) { throw new NumberFormatException("illegal number"); } result -= digit; } } else { throw new NumberFormatException("illegal number"); } if (negative) { if (i > start + 1) { return result; } else { /* Only got "-" */ throw new NumberFormatException("illegal number"); } } else { return -result; } } /** * Convert the bytes within the specified range of the given byte * array into a signed integer . The range extends from * start till, but not including end. <p> */ public static int parseInt(byte[] b, int start, int end) throws NumberFormatException { return parseInt(b, start, end, 10); } /** * Convert the bytes within the specified range of the given byte * array into a signed long in the given radix . The range extends * from start till, but not including end. <p> * * Based on java.lang.Long.parseLong() */ public static long parseLong(byte[] b, int start, int end, int radix) throws NumberFormatException { if (b == null) throw new NumberFormatException("null"); long result = 0; boolean negative = false; int i = start; long limit; long multmin; int digit; if (end > start) { if (b[i] == "-") { negative = true; limit = Long.MIN_VALUE; i++; } else { limit = -Long.MAX_VALUE; } multmin = limit / radix; if (i < end) { digit = Character.digit((char)b[i++], radix); if (digit < 0) { throw new NumberFormatException( "illegal number: " + toString(b, start, end) ); } else { result = -digit; } } while (i < end) { // Accumulating negatively avoids surprises near MAX_VALUE digit = Character.digit((char)b[i++], radix); if (digit < 0) { throw new NumberFormatException("illegal number"); } if (result < multmin) { throw new NumberFormatException("illegal number"); } result *= radix; if (result < limit + digit) { throw new NumberFormatException("illegal number"); } result -= digit; } } else { throw new NumberFormatException("illegal number"); } if (negative) { if (i > start + 1) { return result; } else { /* Only got "-" */ throw new NumberFormatException("illegal number"); } } else { return -result; } } /** * Convert the bytes within the specified range of the given byte * array into a signed long . The range extends from * start till, but not including end. <p> */ public static long parseLong(byte[] b, int start, int end) throws NumberFormatException { return parseLong(b, start, end, 10); } /** * Convert the bytes within the specified range of the given byte * array into a String. The range extends from start * till, but not including end. <p> */ public static String toString(byte[] b, int start, int end) { int size = end - start; char[] theChars = new char[size]; for (int i = 0, j = start; i < size; ) theChars[i++] = (char)(b[j++]&0xff); return new String(theChars); } public static String toString(ByteArrayInputStream is) { int size = is.available(); char[] theChars = new char[size]; byte[] bytes = new byte[size]; is.read(bytes, 0, size); for (int i = 0; i < size;) theChars[i] = (char)(bytes[i++]&0xff); return new String(theChars); } public static byte[] getBytes(String s) { char [] chars= s.toCharArray(); int size = chars.length; byte[] bytes = new byte[size]; for (int i = 0; i < size;) bytes[i] = (byte) chars[i++]; return bytes; } public static byte[] getBytes(InputStream is) throws IOException { int len; int size = 1024; byte [] buf; if (is instanceof ByteArrayInputStream) { size = is.available(); buf = new byte[size]; len = is.read(buf, 0, size); } else { ByteArrayOutputStream bos = new ByteArrayOutputStream(); buf = new byte[size]; while ((len = is.read(buf, 0, size)) != -1) bos.write(buf, 0, len); buf = bos.toByteArray(); } return buf; } } </source>

QP Encoder Stream

   <source lang="java">
   

/*

* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License").  You
* may not use this file except in compliance with the License. You can obtain
* a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code.  If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [year]
* [name of copyright owner]"
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license."  If you don"t indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above.  However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/

/*

* @(#)QPEncoderStream.java 1.8 07/05/04
*/

import java.io.*; /**

* This class implements a Quoted Printable Encoder. It is implemented as
* a FilterOutputStream, so one can just wrap this class around
* any output stream and write bytes into this filter. The Encoding
* is done as the bytes are written out.
* 
* @author John Mani
*/

public class QPEncoderStream extends FilterOutputStream {

   private int count = 0;  // number of bytes that have been output
   private int bytesPerLine; // number of bytes per line
   private boolean gotSpace = false;
   private boolean gotCR = false;
   /**
    * Create a QP encoder that encodes the specified input stream
    * @param out        the output stream
    * @param bytesPerLine  the number of bytes per line. The encoder
    *                   inserts a CRLF sequence after this many number
    *                   of bytes.
    */
   public QPEncoderStream(OutputStream out, int bytesPerLine) {
 super(out);
 // Subtract 1 to account for the "=" in the soft-return 
 // at the end of a line
 this.bytesPerLine = bytesPerLine - 1;
   }
   /**
    * Create a QP encoder that encodes the specified input stream.
    * Inserts the CRLF sequence after outputting 76 bytes.
    * @param out        the output stream
    */
   public QPEncoderStream(OutputStream out) {
 this(out, 76);  
   }
   /**
    * Encodes len bytes from the specified
    * byte array starting at offset off to
    * this output stream.
    *
    * @param      b     the data.
    * @param      off   the start offset in the data.
    * @param      len   the number of bytes to write.
    * @exception  IOException  if an I/O error occurs.
    */
   public void write(byte[] b, int off, int len) throws IOException {
 for (int i = 0; i < len; i++)
     write(b[off + i]);
   }
   /**
    * Encodes b.length bytes to this output stream.
    * @param      b   the data to be written.
    * @exception  IOException  if an I/O error occurs.
    */
   public void write(byte[] b) throws IOException {
 write(b, 0, b.length);
   }
   /**
    * Encodes the specified byte to this output stream.
    * @param      c   the byte.
    * @exception  IOException  if an I/O error occurs.
    */
   public void write(int c) throws IOException {
 c = c & 0xff; // Turn off the MSB.
 if (gotSpace) { // previous character was <SPACE>
     if (c == "\r" || c == "\n")
   // if CR/LF, we need to encode the <SPACE> char
   output(" ", true);
     else // no encoding required, just output the char
   output(" ", false);
     gotSpace = false;
 }
 if (c == "\r") {
     gotCR = true;
     outputCRLF();
 } else {
     if (c == "\n") {
   if (gotCR) 
       // This is a CRLF sequence, we already output the 
       // corresponding CRLF when we got the CR, so ignore this
       ;
   else
       outputCRLF();
     } else if (c == " ") {
   gotSpace = true;
     } else if (c < 040 || c >= 0177 || c == "=")
   // Encoding required. 
   output(c, true);
     else // No encoding required
   output(c, false);
     // whatever it was, it wasn"t a CR
     gotCR = false;
 }
   }
   /**
    * Flushes this output stream and forces any buffered output bytes
    * to be encoded out to the stream.
    * @exception  IOException  if an I/O error occurs.
    */
   public void flush() throws IOException {
 out.flush();
   }
   /**
    * Forces any buffered output bytes to be encoded out to the stream
    * and closes this output stream
    */
   public void close() throws IOException {
 out.close();
   }
   private void outputCRLF() throws IOException {
 out.write("\r");
 out.write("\n");
 count = 0;
   }
   // The encoding table
   private final static char hex[] = {
 "0","1", "2", "3", "4", "5", "6", "7",
 "8","9", "A", "B", "C", "D", "E", "F"
   };
   protected void output(int c, boolean encode) throws IOException {
 if (encode) {
     if ((count += 3) > bytesPerLine) {
   out.write("=");
       out.write("\r");
       out.write("\n");
   count = 3; // set the next line"s length
     }
     out.write("=");
     out.write(hex[c >> 4]);
     out.write(hex[c & 0xf]);
 } else {
     if (++count > bytesPerLine) {
   out.write("=");
       out.write("\r");
       out.write("\n");
   count = 1; // set the next line"s length
     }
     out.write(c);
 }
   }
   /**** begin TEST program ***
   public static void main(String argv[]) throws Exception {
       FileInputStream infile = new FileInputStream(argv[0]);
       QPEncoderStream encoder = new QPEncoderStream(System.out);
       int c;

       while ((c = infile.read()) != -1)
           encoder.write(c);
       encoder.close();
   }
   *** end TEST program ***/

} /*

* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License").  You
* may not use this file except in compliance with the License. You can obtain
* a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code.  If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [year]
* [name of copyright owner]"
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license."  If you don"t indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above.  However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/

/*

* @(#)ASCIIUtility.java  1.11 07/05/04
*/
class ASCIIUtility {
   // Private constructor so that this class is not instantiated
   private ASCIIUtility() { }
 
   /**
    * Convert the bytes within the specified range of the given byte 
    * array into a signed integer in the given radix . The range extends 
    * from start till, but not including end. <p>
    *
    * Based on java.lang.Integer.parseInt()
    */
   public static int parseInt(byte[] b, int start, int end, int radix)
   throws NumberFormatException {
 if (b == null)
     throw new NumberFormatException("null");
 
 int result = 0;
 boolean negative = false;
 int i = start;
 int limit;
 int multmin;
 int digit;
 if (end > start) {
     if (b[i] == "-") {
   negative = true;
   limit = Integer.MIN_VALUE;
   i++;
     } else {
   limit = -Integer.MAX_VALUE;
     }
     multmin = limit / radix;
     if (i < end) {
   digit = Character.digit((char)b[i++], radix);
   if (digit < 0) {
       throw new NumberFormatException(
     "illegal number: " + toString(b, start, end)
     );
   } else {
       result = -digit;
   }
     }
     while (i < end) {
   // Accumulating negatively avoids surprises near MAX_VALUE
   digit = Character.digit((char)b[i++], radix);
   if (digit < 0) {
       throw new NumberFormatException("illegal number");
   }
   if (result < multmin) {
       throw new NumberFormatException("illegal number");
   }
   result *= radix;
   if (result < limit + digit) {
       throw new NumberFormatException("illegal number");
   }
   result -= digit;
     }
 } else {
     throw new NumberFormatException("illegal number");
 }
 if (negative) {
     if (i > start + 1) {
   return result;
     } else {  /* Only got "-" */
   throw new NumberFormatException("illegal number");
     }
 } else {
     return -result;
 }
   }
   /**
    * Convert the bytes within the specified range of the given byte 
    * array into a signed integer . The range extends from 
    * start till, but not including end. <p>
    */
   public static int parseInt(byte[] b, int start, int end)
   throws NumberFormatException {
 return parseInt(b, start, end, 10);
   }
   /**
    * Convert the bytes within the specified range of the given byte 
    * array into a signed long in the given radix . The range extends 
    * from start till, but not including end. <p>
    *
    * Based on java.lang.Long.parseLong()
    */
   public static long parseLong(byte[] b, int start, int end, int radix)
   throws NumberFormatException {
 if (b == null)
     throw new NumberFormatException("null");
 
 long result = 0;
 boolean negative = false;
 int i = start;
 long limit;
 long multmin;
 int digit;
 if (end > start) {
     if (b[i] == "-") {
   negative = true;
   limit = Long.MIN_VALUE;
   i++;
     } else {
   limit = -Long.MAX_VALUE;
     }
     multmin = limit / radix;
     if (i < end) {
   digit = Character.digit((char)b[i++], radix);
   if (digit < 0) {
       throw new NumberFormatException(
     "illegal number: " + toString(b, start, end)
     );
   } else {
       result = -digit;
   }
     }
     while (i < end) {
   // Accumulating negatively avoids surprises near MAX_VALUE
   digit = Character.digit((char)b[i++], radix);
   if (digit < 0) {
       throw new NumberFormatException("illegal number");
   }
   if (result < multmin) {
       throw new NumberFormatException("illegal number");
   }
   result *= radix;
   if (result < limit + digit) {
       throw new NumberFormatException("illegal number");
   }
   result -= digit;
     }
 } else {
     throw new NumberFormatException("illegal number");
 }
 if (negative) {
     if (i > start + 1) {
   return result;
     } else {  /* Only got "-" */
   throw new NumberFormatException("illegal number");
     }
 } else {
     return -result;
 }
   }
   /**
    * Convert the bytes within the specified range of the given byte 
    * array into a signed long . The range extends from 
    * start till, but not including end. <p>
    */
   public static long parseLong(byte[] b, int start, int end)
   throws NumberFormatException {
 return parseLong(b, start, end, 10);
   }
   /**
    * Convert the bytes within the specified range of the given byte 
    * array into a String. The range extends from start
    * till, but not including end. <p>
    */
   public static String toString(byte[] b, int start, int end) {
 int size = end - start;
 char[] theChars = new char[size];
 for (int i = 0, j = start; i < size; )
     theChars[i++] = (char)(b[j++]&0xff);
 
 return new String(theChars);
   }
   public static String toString(ByteArrayInputStream is) {
 int size = is.available();
 char[] theChars = new char[size];
 byte[] bytes    = new byte[size];
 is.read(bytes, 0, size);
 for (int i = 0; i < size;)
     theChars[i] = (char)(bytes[i++]&0xff);
 
 return new String(theChars);
   }
   public static byte[] getBytes(String s) {
 char [] chars= s.toCharArray();
 int size = chars.length;
 byte[] bytes = new byte[size];
     
 for (int i = 0; i < size;)
     bytes[i] = (byte) chars[i++];
 return bytes;
   }
   public static byte[] getBytes(InputStream is) throws IOException {
 int len;
 int size = 1024;
 byte [] buf;
 if (is instanceof ByteArrayInputStream) {
     size = is.available();
     buf = new byte[size];
     len = is.read(buf, 0, size);
 }
 else {
     ByteArrayOutputStream bos = new ByteArrayOutputStream();
     buf = new byte[size];
     while ((len = is.read(buf, 0, size)) != -1)
   bos.write(buf, 0, len);
     buf = bos.toByteArray();
 }
 return buf;
   }

}



 </source>
   
  
 
  



Represents a collection of 64 boolean (on/off) flags.

   <source lang="java">
   

/*

* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import java.io.Serializable; /**

* Represents a collection of 64 boolean (on/off) flags.  Individual flags 
* are represented by powers of 2.  For example,
* Flag 1 = 1
* Flag 2 = 2
* Flag 3 = 4
* Flag 4 = 8

* or using shift operator to make numbering easier:
* Flag 1 = 1 << 0
* Flag 2 = 1 << 1
* Flag 3 = 1 << 2
* Flag 4 = 1 << 3
* * <p> * There cannot be a flag with a value of 3 because that represents Flag 1 * and Flag 2 both being on/true.
*

*
* @version $Revision: 478334 $ $Date: 2006-11-22 21:31:54 +0000 (Wed, 22 Nov 2006) $
*/

public class Flags implements Serializable {

   /**
    * Represents the current flag state.
    */
   private long flags = 0;
   /**
    * Create a new Flags object.
    */
   public Flags() {
       super();
   }
   /**
    * Initialize a new Flags object with the given flags.
    *
    * @param flags collection of boolean flags to represent.
    */
   public Flags(long flags) {
       super();
       this.flags = flags;
   }
   /**
    * Returns the current flags.
    *
    * @return collection of boolean flags represented.
    */
   public long getFlags() {
       return this.flags;
   }
   /**
    * Tests whether the given flag is on.  If the flag is not a power of 2 
    * (ie. 3) this tests whether the combination of flags is on.
    *
    * @param flag Flag value to check.
    *
    * @return whether the specified flag value is on.
    */
   public boolean isOn(long flag) {
       return (this.flags & flag) > 0;
   }
   /**
    * Tests whether the given flag is off.  If the flag is not a power of 2 
    * (ie. 3) this tests whether the combination of flags is off.
    *
    * @param flag Flag value to check.
    *
    * @return whether the specified flag value is off.
    */
   public boolean isOff(long flag) {
       return (this.flags & flag) == 0;
   }
   /**
    * Turns on the given flag.  If the flag is not a power of 2 (ie. 3) this
    * turns on multiple flags.
    *
    * @param flag Flag value to turn on.
    */
   public void turnOn(long flag) {
       this.flags |= flag;
   }
   /**
    * Turns off the given flag.  If the flag is not a power of 2 (ie. 3) this
    * turns off multiple flags.
    *
    * @param flag Flag value to turn off.
    */
   public void turnOff(long flag) {
       this.flags &= ~flag;
   }
   /**
    * Turn off all flags.
    */
   public void turnOffAll() {
       this.flags = 0;
   }
   
   /**
    * Turn off all flags.  This is a synonym for turnOffAll().
    * @since Validator 1.1.1
    */
   public void clear() {
       this.flags = 0;
   }
   /**
    * Turn on all 64 flags.
    */
   public void turnOnAll() {
       this.flags = Long.MAX_VALUE;
   }
   /**
    * Clone this Flags object.
    *
    * @return a copy of this object.
    * @see java.lang.Object#clone()
    */
   public Object clone() {
       try {
           return super.clone();
       } catch(CloneNotSupportedException e) {
           throw new RuntimeException("Couldn"t clone Flags object.");
       }
   }
   /**
    * Tests if two Flags objects are in the same state.
    * @param obj object being tested
    * @see java.lang.Object#equals(java.lang.Object)
    *
    * @return whether the objects are equal.
    */
   public boolean equals(Object obj) {
       if (!(obj instanceof Flags)) {
           return false;
       }
       if (obj == this) {
           return true;
       }
       Flags f = (Flags) obj;
       return this.flags == f.flags;
   }
   /**
    * The hash code is based on the current state of the flags.
    * @see java.lang.Object#hashCode()
    *
    * @return the hash code for this object.
    */
   public int hashCode() {
       return (int) this.flags;
   }
   /**
    * Returns a 64 length String with the first flag on the right and the 
    * 64th flag on the left.  A 1 indicates the flag is on, a 0 means it"s 
    * off.
    *
    * @return string representation of this object.
    */
   public String toString() {
       StringBuffer bin = new StringBuffer(Long.toBinaryString(this.flags));
       for (int i = 64 - bin.length(); i > 0; i--) {
           bin.insert(0, "0");
       }
       return bin.toString();
   }

}



 </source>
   
  
 
  



to Base64

   <source lang="java">
   

/****************************************************************

* Licensed to the Apache Software Foundation (ASF) under one   *
* or more contributor license agreements.  See the NOTICE file *
* distributed with this work for additional information        *
* regarding copyright ownership.  The ASF licenses this file   *
* to you under the Apache License, Version 2.0 (the            *
* "License"); you may not use this file except in compliance   *
* with the License.  You may obtain a copy of the License at   *
*                                                              *
*   http://www.apache.org/licenses/LICENSE-2.0                 *
*                                                              *
* Unless required by applicable law or agreed to in writing,   *
* software distributed under the License is distributed on an  *
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
* KIND, either express or implied.  See the License for the    *
* specific language governing permissions and limitations      *
* under the License.                                           *
****************************************************************/

public class EncodeUtils {

   public static final int MASK = 0x3F;
   public static final int FIRST_MASK = MASK << 18; 
   public static final int SECOND_MASK = MASK << 12; 
   public static final int THIRD_MASK = MASK << 6; 
   public static final int FORTH_MASK = MASK; 
   
   public static final byte[] ENCODING = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N",
       "O", "P" ,"Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i",
       "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3",
       "4", "5", "6", "7", "8", "9", "+", "/"};
   
   public static final void main(String[] args) throws Exception {
       byte[] bytes = {(byte) 0, (byte) 128, (byte) 0};
       System.out.println(new String(toBase64(bytes)));
       System.out.println(new String(toBase64("Hello, World".getBytes())));
       System.out.println(new String(toBase64("Monday".getBytes())));
       System.out.println(new String(toBase64("M\u00F6nchengladbach\r\n".getBytes("ISO-8859-1"))));
   }
   
   public static byte[] toBase64(byte[] in) {
       int inputLength = in.length;
       int outputLength = (int) Math.floor((4*inputLength) / 3f) + 3;
       outputLength = outputLength + 2 * (int) Math.floor(outputLength / 76f);
       byte[] results = new byte[outputLength];
       int inputIndex = 0;
       int outputIndex = 0;
       while (inputLength - inputIndex > 2) {
           int one = (toInt(in[inputIndex++]) << 16);
           int two = (toInt(in[inputIndex++]) << 8);
           int three = toInt(in[inputIndex++]);
           int quantum = one | two | three;
           int index = (quantum & FIRST_MASK) >> 18;
           outputIndex = setResult(results, outputIndex, ENCODING[index]);
           index = (quantum & SECOND_MASK) >> 12;
           outputIndex = setResult(results, outputIndex, ENCODING[index]);
           index = (quantum & THIRD_MASK) >> 6;
           outputIndex = setResult(results, outputIndex, ENCODING[index]);
           index = (quantum & FORTH_MASK);
           outputIndex = setResult(results, outputIndex, ENCODING[index]);
       }
       
       switch (inputLength - inputIndex) {
           case 1:
               int quantum = in[inputIndex++] << 16;
               int index = (quantum & FIRST_MASK) >> 18;
               outputIndex = setResult(results, outputIndex, ENCODING[index]);
               index = (quantum & SECOND_MASK) >> 12;
               outputIndex = setResult(results, outputIndex, ENCODING[index]);
               outputIndex = setResult(results, outputIndex, (byte) "=");
               outputIndex = setResult(results, outputIndex, (byte) "=");
               break;
               
           case 2:
               quantum = (in[inputIndex++] << 16) + (in[inputIndex++] << 8);
               index = (quantum & FIRST_MASK) >> 18;
               outputIndex = setResult(results, outputIndex, ENCODING[index]);
               index = (quantum & SECOND_MASK) >> 12;
               outputIndex = setResult(results, outputIndex, ENCODING[index]);
               index = (quantum & THIRD_MASK) >> 6;
               outputIndex = setResult(results, outputIndex, ENCODING[index]);
               outputIndex = setResult(results, outputIndex, (byte) "=");
               break;
       }
       
       return results;
   }
   private static int toInt(byte b) {
       return 255 & b;
   }
   private static int setResult(byte[] results, int outputIndex, byte value) {
       results[outputIndex++] = value;
       outputIndex = checkLineLength(results, outputIndex);
       return outputIndex;
   }
   private static int checkLineLength(byte[] results, int outputIndex) {
       if (outputIndex == 76 || outputIndex > 76 && (outputIndex - 2*Math.floor(outputIndex/76f - 1)) % 76 == 0) {
           results[outputIndex++] = "\r";
           results[outputIndex++] = "\n";
       }
       return outputIndex;
   }

}



 </source>