Base64 Character decoder as specified in RFC1113.
import java.io.IOException;
import java.io.InputStream;
/**
* This class implements a Base64 Character decoder as specified in RFC1113.
* Unlike some other encoding schemes there is nothing in this encoding that
* tells the decoder where a buffer starts or stops, so to use it you will need
* to isolate your encoded data into a single chunk and then feed them
* this decoder. The simplest way to do that is to read all of the encoded
* data into a string and then use:
* <pre>
* byte data[];
* InputStream is = new ByteArrayInputStream(data);
* is = new Base64DecodeStream(is);
* </pre>
*
* On errors, this class throws a IOException with the following detail
* strings:
* <pre>
* "Base64DecodeStream: Bad Padding byte (2)."
* "Base64DecodeStream: Bad Padding byte (1)."
* </pre>
*
* @author <a href="mailto:thomas.deweese@kodak.com">Thomas DeWeese</a>
* @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
* @author Chuck McManis
* @version $Id: Base64DecodeStream.java 501495 2007-01-30 18:00:36Z dvholten $
*/
public class Base64DecodeStream extends InputStream {
InputStream src;
public Base64DecodeStream(InputStream src) {
this.src = src;
}
private static final byte[] pem_array = new byte[256];
static {
for (int i=0; i<pem_array.length; i++)
pem_array[i] = -1;
int idx = 0;
for (char c='A'; c<='Z'; c++) {
pem_array[c] = (byte)idx++;
}
for (char c='a'; c<='z'; c++) {
pem_array[c] = (byte)idx++;
}
for (char c='0'; c<='9'; c++) {
pem_array[c] = (byte)idx++;
}
pem_array['+'] = (byte)idx++;
pem_array['/'] = (byte)idx++;
}
public boolean markSupported() { return false; }
public void close()
throws IOException {
EOF = true;
}
public int available()
throws IOException {
return 3-out_offset;
}
byte[] decode_buffer = new byte[4];
byte[] out_buffer = new byte[3];
int out_offset = 3;
boolean EOF = false;
public int read() throws IOException {
if (out_offset == 3) {
if (EOF || getNextAtom()) {
EOF = true;
return -1;
}
}
return ((int)out_buffer[out_offset++])&0xFF;
}
public int read(byte []out, int offset, int len)
throws IOException {
int idx = 0;
while (idx < len) {
if (out_offset == 3) {
if (EOF || getNextAtom()) {
EOF = true;
if (idx == 0) return -1;
else return idx;
}
}
out[offset+idx] = out_buffer[out_offset++];
idx++;
}
return idx;
}
final boolean getNextAtom() throws IOException {
int count, a, b, c, d;
int off = 0;
while(off != 4) {
count = src.read(decode_buffer, off, 4-off);
if (count == -1)
return true;
int in=off, out=off;
while(in < off+count) {
if ((decode_buffer[in] != '\n') &&
(decode_buffer[in] != '\r') &&
(decode_buffer[in] != ' '))
decode_buffer[out++] = decode_buffer[in];
in++;
}
off = out;
}
a = pem_array[((int)decode_buffer[0])&0xFF];
b = pem_array[((int)decode_buffer[1])&0xFF];
c = pem_array[((int)decode_buffer[2])&0xFF];
d = pem_array[((int)decode_buffer[3])&0xFF];
out_buffer[0] = (byte)((a<<2) | (b>>>4));
out_buffer[1] = (byte)((b<<4) | (c>>>2));
out_buffer[2] = (byte)((c<<6) | d );
if (decode_buffer[3] != '=') {
// All three bytes are good.
out_offset=0;
} else if (decode_buffer[2] == '=') {
// Only one byte of output.
out_buffer[2] = out_buffer[0];
out_offset = 2;
EOF=true;
} else {
// Only two bytes of output.
out_buffer[2] = out_buffer[1];
out_buffer[1] = out_buffer[0];
out_offset = 1;
EOF=true;
}
return false;
}
}
Related examples in the same category