FileDocCategorySizeDatePackage
Base64Decoder.javaAPI DocExample6376Wed Nov 03 11:59:12 GMT 2004com.oreilly.servlet

Base64Decoder

public class Base64Decoder extends FilterInputStream
A class to decode Base64 streams and strings. See RFC 1521 section 5.2 for details of the Base64 algorithm.

This class can be used for decoding strings:

String encoded = "d2VibWFzdGVyOnRyeTJndWVTUw";
String decoded = Base64Decoder.decode(encoded);
or for decoding streams:
InputStream in = new Base64Decoder(System.in);
author
Jason Hunter, Copyright © 2000
version
1.1, 2002/11/01, added decodeToBytes() to better handle binary data (thanks to Sean Graham)
version
1.0, 2000/06/11

Fields Summary
private static final char[]
chars
private static final int[]
ints
private int
charCount
private int
carryOver
Constructors Summary
public Base64Decoder(InputStream in)
Constructs a new Base64 decoder that reads input from the given InputStream.

param
in the input stream

    super(in);
  
Methods Summary
public static java.lang.Stringdecode(java.lang.String encoded)
Returns the decoded form of the given encoded string, as a String. Note that not all binary data can be represented as a String, so this method should only be used for encoded String data. Use decodeToBytes() otherwise.

param
encoded the string to decode
return
the decoded form of the encoded string

    return new String(decodeToBytes(encoded));
  
public static byte[]decodeToBytes(java.lang.String encoded)
Returns the decoded form of the given encoded string, as bytes.

param
encoded the string to decode
return
the decoded form of the encoded string

    byte[] bytes = null;
    try {
      bytes = encoded.getBytes("8859_1");
    }
    catch (UnsupportedEncodingException ignored) { }

    Base64Decoder in = new Base64Decoder(
                       new ByteArrayInputStream(bytes));
    
    ByteArrayOutputStream out = 
      new ByteArrayOutputStream((int) (bytes.length * 0.67));

    try {
      byte[] buf = new byte[4 * 1024];  // 4K buffer
      int bytesRead;
      while ((bytesRead = in.read(buf)) != -1) {
        out.write(buf, 0, bytesRead);
      }
      out.close();

      return out.toByteArray();
    }
    catch (IOException ignored) { return null; }
  
public static voidmain(java.lang.String[] args)

    if (args.length != 1) {
      System.err.println("Usage: java Base64Decoder fileToDecode");
      return;
    }

    Base64Decoder decoder = null;
    try {
      decoder = new Base64Decoder(
                new BufferedInputStream(
                new FileInputStream(args[0])));
      byte[] buf = new byte[4 * 1024];  // 4K buffer
      int bytesRead;
      while ((bytesRead = decoder.read(buf)) != -1) {
        System.out.write(buf, 0, bytesRead);
      }
    }
    finally {
      if (decoder != null) decoder.close();
    }
  
public intread()
Returns the next decoded character from the stream, or -1 if end of stream was reached.

return
the decoded character, or -1 if the end of the input stream is reached
exception
IOException if an I/O error occurs

    // Read the next non-whitespace character
    int x;
    do {
      x = in.read();
      if (x == -1) {
        return -1;
      }
    } while (Character.isWhitespace((char)x));
    charCount++;

    // The '=' sign is just padding
    if (x == '=") {
      return -1;  // effective end of stream
    }

    // Convert from raw form to 6-bit form
    x = ints[x];

    // Calculate which character we're decoding now
    int mode = (charCount - 1) % 4;

    // First char save all six bits, go for another
    if (mode == 0) {
      carryOver = x & 63;
      return read();
    }
    // Second char use previous six bits and first two new bits,
    // save last four bits
    else if (mode == 1) {
      int decoded = ((carryOver << 2) + (x >> 4)) & 255;
      carryOver = x & 15;
      return decoded;
    }
    // Third char use previous four bits and first four new bits,
    // save last two bits
    else if (mode == 2) {
      int decoded = ((carryOver << 4) + (x >> 2)) & 255;
      carryOver = x & 3;
      return decoded;
    }
    // Fourth char use previous two bits and all six new bits
    else if (mode == 3) {
      int decoded = ((carryOver << 6) + x) & 255;
      return decoded;
    }
    return -1;  // can't actually reach this line
  
public intread(byte[] buf, int off, int len)
Reads decoded data into an array of bytes and returns the actual number of bytes read, or -1 if end of stream was reached.

param
buf the buffer into which the data is read
param
off the start offset of the data
param
len the maximum number of bytes to read
return
the actual number of bytes read, or -1 if the end of the input stream is reached
exception
IOException if an I/O error occurs

    if (buf.length < (len + off - 1)) {
      throw new IOException("The input buffer is too small: " + len + 
       " bytes requested starting at offset " + off + " while the buffer " +
       " is only " + buf.length + " bytes long.");
    }

    // This could of course be optimized
    int i;
    for (i = 0; i < len; i++) {
      int x = read();
      if (x == -1 && i == 0) {  // an immediate -1 returns -1
        return -1;
      }
      else if (x == -1) {       // a later -1 returns the chars read so far
        break;
      }
      buf[off + i] = (byte) x;
    }
    return i;