Mega Code Archive

 
Categories / Java / File Input Output
 

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;     } }