//============================================================================== // tribble/util/Base64Encoder.java //============================================================================== package tribble.util; // System imports import java.lang.String; import java.text.ParseException; // Local imports // (None) /******************************************************************************* * Base-64 encoding methods. * *
* Base-64 encoding (a.k.a. radix-64 encoding) is a form of encoding binary data * in 6-bit units. (6 bits provides 64 distinct binary values, hence the moniker * base-64 or radix-64.) Groups of three 8-bit octets (bytes), * totalling 24 bits, can be converted into four 6-bit units. Each 6-bit unit * can in turn be represented by one of 64 unique printable ASCII (8-bit) * characters. * *
* Converting straight binary data (as a sequence of 8-bit octets) into a * base-64 representation is thus simply the the process of packing groups of * three 8-bit octets into four 6-bit units, and then substituting each 6-bit * unit with its corresponding ASCII character code. * *
* Converting base-64 encoded data (as a sequence of 8-bit characters) back into * straight binary data is the reverse operation, substituting each base-64 * ASCII character code with its corresponding 6-bit unit, then unpacking groups * of four 6-bit units into three 8-bit octets. * *
* A 65th special ASCII character is used to indicate trailing padding in * base-64 encoded data. * *
* This class can be used as a simple replacement for the
* {@link sun.misc.BASE64Encoder} class.
*
*
* @version $Revision: 1.2 $ $Date: 2005/04/10 20:05:52 $
* @since 2003-02-26
* @author
* David R. Tribble
* (david@tribble.com).
*
*
* Copyright ©2003-2005 by David R. Tribble, all rights reserved.
*
* Permission is granted to freely use and distribute this source
* code provided that the original copyright and authorship notices
* remain intact.
*
* @see Base64Decoder
* @see sun.misc.BASE64Encoder
*/
public class Base64Encoder
{
// Identification
/** Revision information. */
static final String REV =
"@(#)tribble/util/Base64Encoder.java $Revision: 1.2 $ $Date: 2005/04/10 20:05:52 $\n";
/** Class revision number. */
public static final int SERIES = 102;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Public static methods
/***************************************************************************
* Encode binary data as base-64 characters.
*
*
* @param data (const)
* Binary data, as an array of bytes (8-bit octets).
*
* @return
* A printable ASCII string containing the contents of data encoded
* as base-64 characters. This string will contain
* data.length*4/3+p characters, where p is
* 0, 1, or 2, so as to make the total output length a multiple of 4.
*
* @see #encodeAsString(byte[], int, int) encodeAsString()
* @see Base64Decoder#decodeString(String) Base64Decoder.decodeString()
*
* @since 1.1, 2003-02-26
*/
public static String encodeAsString(/*const*/ byte[] data)
{
// Encode the binary data as base-64 characters
return (encodeAsString(data, 0, data.length));
}
/***************************************************************************
* Encode binary data as base-64 characters.
*
*
* @param data (const)
* Binary data, as an array of bytes (8-bit octets).
*
* @param off
* Index of the first byte (octet) within data to encode.
*
* @param len
* Number of bytes (octets) within data to encode.
*
* @return
* A printable ASCII string containing the contents of data encoded
* as base-64 characters. This string will contain
* len*4/3+p characters, where p is
* 0, 1, or 2, so as to make the total output length a multiple of 4.
*
* @see #encodeAsBytes(byte[], int, int) encodeAsBytes()
* @see Base64Decoder#decodeString(String, byte[], int)
* Base64Decoder.decodeString()
*
* @since 1.1, 2003-02-26
*/
public static String encodeAsString(/*const*/ byte[] data, int off, int len)
{
byte[] b;
// Encode 8-bit bytes as base-64 character bytes
b = encodeAsBytes(data, off, len);
// Return the encoded character bytes as a string
return (new String(b));
}
/***************************************************************************
* Encode binary data as base-64 character octets.
*
*
* @param data (const)
* Binary data, as an array of bytes (8-bit octets).
*
* @return
* An array of bytes containing printable ASCII characters representating the
* contents of data encoded as base-64 characters. This array will
* contain data.length*4/3+p characters, where
* p is 0, 1, or 2, so as to make the total output length a
* multiple of 4.
*
* @see #encodeAsBytes(byte[], int, int) encodeAsBytes()
* @see Base64Decoder#decodeBytes(byte[]) Base64Decoder.decodeBytes()
*
* @since 1.1, 2005-04-01
*/
public static byte[] encodeAsBytes(/*const*/ byte[] data)
{
// Encode the binary data as base-64 characters
return (encodeAsBytes(data, 0, data.length));
}
/***************************************************************************
* Encode binary data as base-64 characters.
*
*
* @param data (const)
* Binary data, as an array of bytes (8-bit octets).
*
* @param off
* Index of the first byte (octet) within data to encode.
*
* @param len
* Number of bytes (octets) within data to encode.
*
* @return
* An array of bytes containing printable ASCII characters containing the
* contents of data encoded as base-64 characters. This array will
* contain data.length*4/3+p characters, where
* p is 0, 1, or 2, so as to make the total output length a
* multiple of 4.
*
* @see #encodeAsBytes(byte[], int, int, byte[], int) encodeAsBytes()
* @see Base64Decoder#decodeBytes(byte[], int, int)
* Base64Decoder.decodeBytes()
*
* @since 1.1, 2005-04-01
*/
public static byte[] encodeAsBytes(/*const*/ byte[] data, int off, int len)
{
byte[] enc;
int olen;
// Allocate the output buffer
olen = (data.length+3-1)/3*4;
enc = new byte[olen];
// Encode the binary data as base-64 characters
encodeAsBytes(data, off, len, enc, 0);
return (enc);
}
/***************************************************************************
* Encode binary data as base-64 characters.
*
*
* Base-64 (a.k.a. radix-64) encoding converts 8-bit bytes (octets) into * characters by encoding 6 bits of data (sextets) in each output character; * thus 3 8-bit input bytes can be converted into 4 6-bit output characters * (for a total of 24 data bits). Any input bytes left over (two or less) * are converted and padded. * *
* +---------------+---------------+---------------+
* | octet | octet | octet |
* |7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0| input octets
* :- - - - - -:- -:- - - -:- - - -:- -:- - - - - -:
* |5 4 3 2 1 0|5 4 3 2 1 0|5 4 3 2 1 0|5 4 3 2 1 0| output sextets
* | sextet | sextet | sextet | sextet |
* +-----------+-----------+-----------+-----------+
*
* +---------------+---------------+ - - - - - - - +
* | octet | octet | no data :
* |7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0| : input octets
* :- - - - - -:- -:- - - -:- - - -:- -:- - - - - -:
* |5 4 3 2 1 0|5 4 3 2 1 0|5 4 3 2 z z| '=' | output sextets
* | sextet | sextet | sextet | padding |
* +-----------+-----------+-----------+-----------+
*
* +---------------+ - - - - - - - + - - - - - - - +
* | octet | no data : no data :
* |7 6 5 4 3 2 1 0| : : input octets
* :- - - - - -:- -:- - - -:- - - -:- -:- - - - - -:
* |5 4 3 2 1 0|5 4 z z z z| '=' | '=' | output sextets
* | sextet | sextet | padding | padding |
* +-----------+-----------+-----------+-----------+
*
* * For example, the following table list some octet sequences and their * resulting sextet encodings: *
* 11,11,11 => 04,11,04,11
* 11,22,33 => 04,12,08,33
* FF,FF,FF => 3F,3F,3F,3F
* 11,11 => 04,11,04, =
* FF,FF => 3F,3F,3C, =
* 11 => 04,10, =, =
* FF => 3F,30, =, =
* FF,00,FF,00,FF,00 => 3F,30,03,3F,00,0F,3C,00
*
*
* @param data (const)
* Binary data, as an array of bytes (8-bit octets).
*
* @param off
* Index of the first byte (octet) within data to encode.
*
* @param len
* Number of bytes (octets) within data to encode.
*
* @param enc
* An array of bytes into which will be written printable ASCII characters
* representating the contents of data encoded as base-64
* characters.
*
* @param encOff
* Index of the first byte (octet) within enc to write to.
*
* @return
* The number of bytes (8-bit octets) actually written into enc.
* This will be exactly len*4/3+p bytes, where
* p is 0, 1, or 2, so as to make the total output length a
* multiple of 4.
*
* @see #encodeAsBytes(byte[], int, int, byte[], int) encodeAsBytes()
* @see Base64Decoder#decodeBytes(byte[], int, int)
* Base64Decoder.decodeBytes()
*
* @since 1.1, 2005-04-01
*/
public static int encodeAsBytes(/*const*/ byte[] data, int off, int len,
byte[] enc, int encOff)
{
int d;
int i;
int o;
// Convert the input bytes in chunks, 24 bits (3 octets) at a time
len += off;
i = off;
o = encOff;
while (i < len-2)
{
// Convert a single 24-bit chunk (3 octets into 4 sextets)
d = ((data[i+0] & 0xFF) << 16) |
((data[i+1] & 0xFF) << 8) |
((data[i+2] & 0xFF));
i += 3;
enc[o++] = toBase64((d >> 18) & 0x3F);
enc[o++] = toBase64((d >> 12) & 0x3F);
enc[o++] = toBase64((d >> 6) & 0x3F);
enc[o++] = toBase64((d) & 0x3F);
}
// Convert leftover input bytes, if any
if (i < len-1)
{
// Two input bytes left, requires one padding char
d = ((data[i+0] & 0xFF) << 16) |
((data[i+1] & 0xFF) << 8);
enc[o++] = toBase64((d >> 18) & 0x3F);
enc[o++] = toBase64((d >> 12) & 0x3F);
enc[o++] = toBase64((d >> 6) & 0x3F);
enc[o++] = '=';
}
else if (i < len)
{
// One input byte left, requires two padding chars
d = ((data[i+0] & 0xFF) << 16);
enc[o++] = toBase64((d >> 18) & 0x3F);
enc[o++] = toBase64((d >> 12) & 0x3F);
enc[o++] = '=';
enc[o++] = '=';
}
// Done
return (o-encOff);
}
/***************************************************************************
* Convert a 6-bit binary value into its corresponding base-64 printable
* ASCII character code.
*
*
* @param bits
* A 6-bit binary value in the range [0,63]; or the value 64, indicating the
* special trailing padding character code; or the character '?',
* indicating an invalid 6-bit code.
*
* @return
* A printable ASCII character code.
*
* @see Base64Decoder#fromBase64 Base64Decoder.fromBase64()
*
* @since 1.1, 2003-02-26
*/
public static byte toBase64(int bits)
{
// This averages 2.85 comparisons per call
if (bits >= 52)
{
if (bits < 62)
return ((byte) (bits-52+'0'));
if (bits == 62)
return ((byte) '+');
if (bits == 63)
return ((byte) '/');
if (bits == 64)
return ((byte) '=');
return ((byte) '?');
}
if (bits >= 26)
return ((byte) (bits-26+'a'));
if (bits >= 0)
return ((byte) (bits-0+'A'));
return ((byte) '?');
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Variables
// (None)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Public constructors
/***************************************************************************
* Default constructor.
*
* * This constructor is provided for compatibility with the * {@link sun.misc.BASE64Encoder} class, which allows this class to be used * as a simple replacement for it. * * @since 1.2, 2005-04-10 */ public Base64Encoder() { // Do nothing } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Public methods /*************************************************************************** * Encode binary data as base-64 characters. * *
* This method produces the same result as the encode() method * of the {@link sun.misc.BASE64Encoder} class. * * * @param data (const) * Binary data, as an array of bytes (8-bit octets). * * @return * A printable ASCII string containing the contents of data encoded * as base-64 characters. This string will contain * data.length*4/3+p characters, where p is * 0, 1, or 2, so as to make the total output length a multiple of 4. * * @see #encodeAsString(byte[]) encodeAsString() * @see Base64Decoder#decodeString(String) Base64Decoder.decodeString() * * @since 1.2, 2005-04-10 */ public String encode(/*const*/ byte[] data) { // Encode the binary data as base-64 characters return (encodeAsString(data, 0, data.length)); } } // End Base64Encoder.java