Argh! Det gik ikke så godt med det link, så jeg smider hele sourcen her:
// cmp.Encode.Base64.java
package cmp.Encode;
/**
* Freeware from:
* Roedy Green
* Canadian Mind Products
* #208 - 525 Ninth Street
* New Westminster, BC Canada V3M 5T9
* tel: (604) 777-1804
* mailto:roedy@mindprod.com
*/
/**
* Encode arbitrary binary into printable ASCII using BASE64 encoding.
* very loosely based on the Base64 Reader by
* Dr. Mark Thornton
* Optrak Distribution Software Ltd.
*
http://www.optrak.co.uk * and Kevin Kelley\'s
http://www.ruralnet.net/~kelley/java/Base64.java *
* Base64 is a way of encoding 8-bit characters using only ASCII
printable
* characters. The spec is described in RFC 2045. Base64 is a scheme
where
* 3 bytes are concatenated, then split to form 4 groups of 6-bits
each; and
* each 6-bits gets translated to an encoded printable ASCII
character, via a
* table lookup. An encoded string is therefore longer than the
original by
* about 1/3. The \"=\" character is used to pad the end. Base64 is
used,
* among other things, to encode the user:password string in an
* Authorization: header for HTTP. Don\'t confuse Base64 with
* x-www-form-urlencoded which is handled by
* Java.net.URLEncoder.encode/decode
* If you wanted to encode a giant file, you could do it in large
chunks that
* are even multiples of 3 bytes, except for the last chunk, and
append the outputs.
*
* version 1.1 1999 December 04 -- more symmetrical encoding
algorithm.
* more accurate StringBuffer
allocation size.
* version 1.0 1999 December 03 -- posted in
comp.lang.java.programmer.
*/
public class Base64
{
/**
* Encode an arbitrary array of bytes as Base64 printable ASCII.
* It will be broken into lines of 72 chars each. The last line
is not
* terminated with a line separator.
*/
public static String encode(byte[] b)
{
// Each group or partial group of 3 bytes becomes four chars
int outputLength = ((b.length + 2) / 3) * 4;
// account for embedded newlines
outputLength += (outputLength / lineLength) *
lineSeparator.length();
// must be local for recursion to work.
StringBuffer sb = new StringBuffer( outputLength );
// must be local for recursion to work.
int linePos = 0;
// first deal with even multiples of 3 bytes.
int len = (b.length / 3) * 3;
int leftover = b.length - len;
for ( int i=0; i<len; i+=3 )
{
// Start a new line if next 4 chars won\'t fit on the
current line
// We don\'t encapsulate so that linePos and sb will work
recursively
{
linePos += 4;
if ( linePos > lineLength )
{
linePos = 0;
if ( lineLength != 0) {sb.append(lineSeparator);}
}
}
// get next three bytes in unsigned form lined up,
// in big-endian order
int combined = b[i+0] & 0xff;
combined <<= 8;
combined |= b[i+1] & 0xff;
combined <<= 8;
combined |= b[i+2] & 0xff;
// break those 24 bits into a 4 groups of 6 bits,
// working LSB to MSB.
int c3 = combined & 0x3f;
combined >>>= 6;
int c2 = combined & 0x3f;
combined >>>= 6;
int c1 = combined & 0x3f;
combined >>>= 6;
int c0 = combined & 0x3f;
// Translate into the equivalent alpha character
// emitting them in big-endian order.
sb.append( valueToChar[c0]);
sb.append( valueToChar[c1]);
sb.append( valueToChar[c2]);
sb.append( valueToChar[c3]);
}
// deal with leftover bytes
switch ( leftover )
{
case 0:
default:
// nothing to do
break;
case 1:
// One leftover byte generates xx==
// Start a new line if next 4 chars won\'t fit on the
current line
// We don\'t encapsulate so that linePos and sb will
work recursively
{
linePos += 4;
if ( linePos > lineLength )
{
linePos = 0;
if ( lineLength != 0)
{sb.append(lineSeparator);}
}
}
// Handle this recursively with a faked complete
triple.
// Throw away last two chars and replace with ==
sb.append(encode(new byte[] {b[len], 0, 0}
).substring(0,2));
sb.append(\"==\");
break;
case 2:
// Two leftover bytes generates xxx=
// Start a new line if next 4 chars won\'t fit on the
current line
// We don\'t encapsulate so that linePos and sb will
work recursively
{
linePos += 4;
if ( linePos > lineLength )
{
linePos = 0;
if ( lineLength != 0)
{sb.append(lineSeparator);}
}
}
// Handle this recursively with a faked complete
triple.
// Throw away last char and replace with =
sb.append(encode(new byte[] {b[len], b[len+1], 0}
).substring(0,3));
sb.append(\"=\");
break;
} // end switch;
if ( outputLength != sb.length() ) System.out.println(\"oops\");
return sb.toString();
}// end encode
/**
* how we separate lines, e.g. \\n, \\r\\n, \\r etc.
*/
static String lineSeparator = System.getProperty( \"line.separator\"
);
/**
* decode a well-formed complete Base64 string back into an array
of bytes.
*/
public static byte[] decode( String s)
{
// estimate worst case size of output array, no embedded
newlines.
byte[] b = new byte[(s.length() / 4) * 3];
// tracks where we are in a cycle of 4 input chars.
int cycle = 0;
// where we combine 4 groups of 6 bits and take apart as 3
groups of 8.
int combined = 0;
// how many bytes we have prepared.
int j = 0;
int len = s.length();
for ( int i=0; i<len; i++ )
{
int c = s.charAt(i);
int value = (c <= 255) ? charToValue[c] : IGNORE;
// there are two magic values PAD (=) and IGNORE.
switch ( value )
{
case IGNORE:
// e.g. \\n, just ignore it.
break;
case PAD:
break;
default:
/* regular value character */
switch ( cycle )
{
case 0:
combined = value;
cycle = 1;
break;
case 1:
combined <<= 6;
combined |= value;
cycle = 2;
break;
case 2:
combined <<= 6;
combined |= value;
cycle = 3;
break;
case 3:
combined <<= 6;
combined |= value;
// we have just completed a cycle of 4
chars.
// the four 6-bit values are in combined
in big-endian order
// peel them off 8 bits at a time working
lsb to msb
// to get our original 3 8-bit bytes back
b[j+2] = (byte)combined;
combined >>>= 8;
b[j+1] = (byte)combined;
combined >>>= 8;
b[j+0] = (byte)combined;
j += 3;
cycle = 0;
break;
}
break;
}
}
// to come.
return null;
}// end decode
/**
* max chars per line. A multiple of 4.
*/
private static int lineLength = 72;
/**
* determines how long the lines are that are generated by encode.
* Ignored by decode.
* @param length 0 means no newlines inserted.
*/
public static void setLineLength(int length)
{
lineLength = length;
}
/**
* letter of the alphabet used to encode binary values 0..63
*/
static final char[] valueToChar = new char[64];
/**
* binary value encoded by a given letter of the alphabet 0..63
*/
static final int[] charToValue = new int[256];
/**
* Marker value for chars we just ignore, e.g. \\n \\r high ascii
*/
static final int IGNORE = -1;
/**
* Marker for = trailing pad
*/
static final int PAD = -2;
static
{
// build translate valueToChar table only once.
// 0..25 -> \'A\'..\'Z\'
for ( int i=0; i<=25; i++ )
valueToChar[i] = (char)(\'A\'+i);
// 26..51 -> \'a\'..\'z\'
for ( int i=0; i<=25; i++ )
valueToChar[i+26] = (char)(\'a\'+i);
// 52..61 -> \'0\'..\'9\'
for ( int i=0; i<=9; i++ )
valueToChar[i+52] = (char)(\'0\'+i);
valueToChar[62] = \'+\';
valueToChar[63] = \'/\';
// build translate charToValue table only once.
for ( int i=0; i<256; i++ )
{
charToValue[i] = IGNORE; // default is to ignore
}
for ( int i=0; i<64; i++ )
{
charToValue[valueToChar[i]] = i;
}
charToValue[\'=\'] = PAD;
}
/**
* used to disable test driver
*/
private static final boolean debug = true;
/**
* test driver
*/
public static void main(String[] args)
{
if ( debug )
{
byte[] a = { (byte)0xfc, (byte)0x0f, (byte)0xc0};
byte[] b = { (byte)0x03, (byte)0xf0, (byte)0x3f};
byte[] c = { (byte)0x00, (byte)0x00, (byte)0x00};
byte[] d = { (byte)0xff, (byte)0xff, (byte)0xff};
byte[] e = { (byte)0xfc, (byte)0x0f, (byte)0xc0, (byte)1};
byte[] f = { (byte)0xfc, (byte)0x0f, (byte)0xc0, (byte)1,
(byte)2};
byte[] g = { (byte)0xfc, (byte)0x0f, (byte)0xc0, (byte)1,
(byte)2, (byte)3};
System.out.println(Base64.encode(a));
System.out.println(Base64.encode(b));
System.out.println(Base64.encode(c));
System.out.println(Base64.encode(d));
System.out.println(Base64.encode(e));
System.out.println(Base64.encode(f));
System.out.println(Base64.encode(g));
for ( int i=0; i<64; i++ )
{
c[2] = (byte)i;
System.out.println(Base64.encode(c));
}
}
}// end main
} // end Base64