A little while ago, I wrote a base64 {en,de}coder in Java. Huzzah. Since I've 
found out that you guys wrote one too, I thought I should submit mine. It's 
implemented as an OutputStream and InputStream pair, though, so it's a bit 
different from yours, which is why I thought to send mine. It's public 
domain, so do whatever you want with it. The two source files are attached.

Alex.
// This software code is hereby placed into the public domain by the author, Alexander Hvostov <[EMAIL PROTECTED]>.
package org.dyndns.aoi;

import java.io.*;
import java.net.ProtocolException;

public class Base64DecoderStream extends FilterInputStream {
	public Base64DecoderStream(InputStream in) { super(in); }
	
	public int available() throws IOException {
		int avail = in.available();
		
		if (avail < 4)
			return 0;
		else if (avail == 4)
			return 1;
		else
			return ((in.available() / 4) * 3) - 1;
	}
	
	public void mark(int readlimit) {}
	public void reset() {}
	public boolean markSupported() { return false; }
	public long skip(long n) { return 0L; }
	
	private byte[] buf = new byte[3];
	private boolean[] fill = new boolean[] { false, false, false };
	private int next = 3;
	
	private void fillBuffer() throws IOException {
		byte[] b = new byte[4];
		int a = 0;
		boolean[] _fill = new boolean[4];
		
		if (in.read(b) < 4)
			throw new EOFException();
		
		for (int i = 0; i < 4; i++) {
			if (b[i] == (byte) '=') {
				for (int j = i; j < 4; j++) {
					b[j] = (byte) 0;
					_fill[j] = false;
				}
				break;
			}
			else {
				_fill[i] = true;
				int idx = Base64EncoderStream.TRANS.indexOf(b[i]);
				if (idx == -1)
					throw new ProtocolException("Illegal character in base64-encoded text.");
				b[i] = (byte) idx;
			}
		}
		
		a |= (((int) b[0]) & 63) << 18;
		a |= (((int) b[1]) & 63) << 12;
		a |= (((int) b[2]) & 63) << 6;
		a |= ((int) b[3]) & 63;
		
		buf[0] = (byte) ((a >> 16) & 255);
		buf[1] = (byte) ((a >> 8) & 255);
		buf[2] = (byte) (a & 255);
		
		fill[0] = _fill[0] && _fill[1];
		fill[1] = _fill[1] && _fill[2];
		fill[2] = _fill[2] && _fill[3];
	}
	
	public int read(byte[] b, int off, int len) throws IOException {
		if (next == 4)
			// Special value indicating EOF.
			return -1;
		
		int count;
		
		for (count = 0; count < len; count++) {
			assert next <= 3;
			if (next == 3) {
				next = 0;
				try {
					fillBuffer();
				}
				catch (EOFException e) {
					next = 4;
					break;
				}
			}
			else if (!fill[next]) {
				break;
			}
			
			b[off + count] = buf[next];
			
			next++;
		}
		
		if (count > 0)
			return count;
		else
			// Return value of 0 is illegal!
			return -1;
	}
	
	public int read(byte[] b) throws IOException {
		return read(b, 0, b.length);
	}
	
	public int read() throws IOException {
		byte[] b = new byte[1];
		if (read(b) == -1)
			return -1;
		else
			return b[0];
	}
	
	public static byte[] decode(byte[] in) throws IOException {
		ByteArrayInputStream bs = new ByteArrayInputStream(in);
		Base64DecoderStream s = new Base64DecoderStream(bs);
		ByteArrayOutputStream out = new ByteArrayOutputStream((in.length * 3) / 4);
		
		Utilities.relay(s, out);
		
		return out.toByteArray();
	}
}
// This software code is hereby placed into the public domain by the author, Alexander Hvostov <[EMAIL PROTECTED]>.
package org.dyndns.aoi;

import java.io.*;

public class Base64EncoderStream extends FilterOutputStream {
	public static final String TRANS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
	
	private int buf = 0;
	private int bufpos = 0;
	private byte[] o = new byte[4];
	
	public Base64EncoderStream(OutputStream out) {
		super(out);
	}
	
	public void close() throws IOException {
		flushBase64();
		out.close();
	}
	
	public void flushBase64() throws IOException {
		if (bufpos == 0)
			// Nothing to flush.
			return;
		
		assert bufpos <= 3;
		
		o[0] = (byte) ((buf >> 18) & 63);
		o[1] = (byte) ((buf >> 12) & 63);
		o[2] = (byte) ((buf >> 6) & 63);
		o[3] = (byte) (buf & 63);
		
		for (int i = 0; i < 4; i++) {
			if (bufpos < i)
				o[i] = (byte) '=';
			else
				o[i] = (byte) TRANS.charAt(o[i]);
		}
		
		out.write(o);
		
		bufpos = buf = 0;
		o[0] = o[1] = o[2] = o[3] = (byte) 0;
	}
	
	public void write(byte[] b, int off, int len) throws IOException {
		for (int i = off; i < off + len; i++) {
			buf |= (((int) b[i]) << (8 * (2 - bufpos)));
			bufpos++;
			if (bufpos == 3)
				flushBase64();
		}
	}
	
	public void write(byte[] b) throws IOException {
		write(b, 0, b.length);
	}
	
	public void write(int b) throws IOException {
		byte[] a = new byte[1];
		a[0] = (byte) b;
		write(a);
	}
	
	public static byte[] encode(byte[] in) throws IOException {
		ByteArrayOutputStream bs = new ByteArrayOutputStream((in.length * 4) / 3);
		Base64EncoderStream s = new Base64EncoderStream(bs);
		s.write(in);
		s.close();
		return bs.toByteArray();
	}
}

Attachment: pgp00000.pgp
Description: signature

Reply via email to