Base64 encoding from DbUnit.org : Base64 Stream « File Input Output « Java






Base64 encoding from DbUnit.org

    
/*
 *
 * The DbUnit Database Testing Framework
 * Copyright (C)2002-2004, DbUnit.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

import java.io.FileInputStream;


/**
 * <p>
 * I am placing this code in the Public Domain. Do with it as you will.
 * This software comes with no guarantees or warranties but with
 * plenty of well-wishing instead!
 * Please visit <a href="http://iharder.net/base64">http://iharder.net/base64</a>
 * periodically to check for updates or to contribute improvements.
 * </p>
 *
 * @author Robert Harder (rharder@usa.net)
 * @author Last changed by: $Author: gommma $
 * @version $Revision: 769 $ $Date: 2008-08-02 09:31:15 +0200 (sab, 02 ago 2008) $
 * @since 1.3
 */
public class Base64
{


    /** Specify encoding (value is <tt>true</tt>). */
    public final static boolean ENCODE = true;


    /** Specify decoding (value is <tt>false</tt>). */
    public final static boolean DECODE = false;


    /** Maximum line length (76) of Base64 output. */
    private final static int MAX_LINE_LENGTH = 76;


    /** The equals sign (=) as a byte. */
    private final static byte EQUALS_SIGN = (byte)'=';


    /** The new line character (\n) as a byte. */
    private final static byte NEW_LINE = (byte)'\n';


    /** The 64 valid Base64 values. */
    private final static byte[] ALPHABET =
            {
                (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G',
                (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N',
                (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U',
                (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z',
                (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g',
                (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n',
                (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u',
                (byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z',
                (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5',
                (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'+', (byte)'/'
            };

    /**
     * Translates a Base64 value to either its 6-bit reconstruction value
     * or a negative number indicating some other meaning.
     **/
    private final static byte[] DECODABET =
            {
                -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal  0 -  8
                -5, -5, // Whitespace: Tab and Linefeed
                -9, -9, // Decimal 11 - 12
                -5, // Whitespace: Carriage Return
                -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - 26
                -9, -9, -9, -9, -9, // Decimal 27 - 31
                -5, // Whitespace: Space
                -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 42
                62, // Plus sign at decimal 43
                -9, -9, -9, // Decimal 44 - 46
                63, // Slash at decimal 47
                52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine
                -9, -9, -9, // Decimal 58 - 60
                -1, // Equals sign at decimal 61
                -9, -9, -9, // Decimal 62 - 64
                0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // Letters 'A' through 'N'
                14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // Letters 'O' through 'Z'
                -9, -9, -9, -9, -9, -9, // Decimal 91 - 96
                26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // Letters 'a' through 'm'
                39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // Letters 'n' through 'z'
                -9, -9, -9, -9                                 // Decimal 123 - 126
                /*,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 127 - 139
                -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 140 - 152
                -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 153 - 165
                -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 166 - 178
                -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 179 - 191
                -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 192 - 204
                -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 205 - 217
                -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 218 - 230
                -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,     // Decimal 231 - 243
                -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9         // Decimal 244 - 255 */
            };

    private final static byte BAD_ENCODING = -9; // Indicates error in encoding
    private final static byte WHITE_SPACE_ENC = -5; // Indicates white space in encoding
    private final static byte EQUALS_SIGN_ENC = -1; // Indicates equals sign in encoding


    /** Defeats instantiation. */
    private Base64()
    {
    }


    /** Testing. */
    public static void main(String[] args)
    {

        String s = "Hello, world";
        s = "abcd";
        //s = System.getProperties().toString();
        //System.out.println( s + ": \n [" + encode( s ) + "]\n [" + decode(encode(s)) + "]" );

        byte[] b = encodeString(s).getBytes();
        byte[] c = decode(b, 0, b.length);

        System.out.println("\n\n" + s + ":" + new String(b) + ":" + new String(c));

        try
        {
            FileInputStream fis = new FileInputStream("c:\\abcd.txt");
            InputStream b64is = new InputStream(fis, DECODE);
            int ib = 0;
            while ((ib = b64is.read()) > 0)
            {   //System.out.print( new String( ""+(char)ib ) );
            }
        }   // end try
        catch (Exception e)
        {
           

            e.printStackTrace();
        }
    }


/* ********  E N C O D I N G   M E T H O D S  ******** */


    /**
     * Encodes the first three bytes of array <var>threeBytes</var>
     * and returns a four-byte array in Base64 notation.
     *
     * @param threeBytes the array to convert
     * @return four byte array in Base64 notation.
     * @since 1.3
     */
    private static byte[] encode3to4(byte[] threeBytes)
    {
      

        return encode3to4(threeBytes, 3);
    }   // end encodeToBytes


    /**
     * Encodes up to the first three bytes of array <var>threeBytes</var>
     * and returns a four-byte array in Base64 notation.
     * The actual number of significant bytes in your array is
     * given by <var>numSigBytes</var>.
     * The array <var>threeBytes</var> needs only be as big as
     * <var>numSigBytes</var>.
     *
     * @param threeBytes the array to convert
     * @param numSigBytes the number of significant bytes in your array
     * @return four byte array in Base64 notation.
     * @since 1.3
     */
    private static byte[] encode3to4(byte[] threeBytes, int numSigBytes)
    {
     
        byte[] dest = new byte[4];
        encode3to4(threeBytes, 0, numSigBytes, dest, 0);
        return dest;
    }


    /**
     * Encodes up to three bytes of the array <var>source</var>
     * and writes the resulting four Base64 bytes to <var>destination</var>.
     * The source and destination arrays can be manipulated
     * anywhere along their length by specifying
     * <var>srcOffset</var> and <var>destOffset</var>.
     * This method does not check to make sure your arrays
     * are large enough to accomodate <var>srcOffset</var> + 3 for
     * the <var>source</var> array or <var>destOffset</var> + 4 for
     * the <var>destination</var> array.
     * The actual number of significant bytes in your array is
     * given by <var>numSigBytes</var>.
     *
     * @param source the array to convert
     * @param srcOffset the index where conversion begins
     * @param numSigBytes the number of significant bytes in your array
     * @param destination the array to hold the conversion
     * @param destOffset the index where output will be put
     * @return the <var>destination</var> array
     * @since 1.3
     */
    private static byte[] encode3to4(
            byte[] source, int srcOffset, int numSigBytes,
            byte[] destination, int destOffset)
    {
        //           1         2         3
        // 01234567890123456789012345678901 Bit position
        // --------000000001111111122222222 Array position from threeBytes
        // --------|    ||    ||    ||    | Six bit groups to index ALPHABET
        //          >>18  >>12  >> 6  >> 0  Right shift necessary
        //                0x3f  0x3f  0x3f  Additional AND

        // Create buffer with zero-padding if there are only one or two
        // significant bytes passed in the array.
        // We have to shift left 24 in order to flush out the 1's that appear
        // when Java treats a value as negative that is cast from a byte to an int.
        int inBuff = (numSigBytes > 0 ? ((source[srcOffset] << 24) >>> 8) : 0)
                | (numSigBytes > 1 ? ((source[srcOffset + 1] << 24) >>> 16) : 0)
                | (numSigBytes > 2 ? ((source[srcOffset + 2] << 24) >>> 24) : 0);

        switch (numSigBytes)
        {
            case 3:
                destination[destOffset] = ALPHABET[(inBuff >>> 18)];
                destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f];
                destination[destOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3f];
                destination[destOffset + 3] = ALPHABET[(inBuff) & 0x3f];
                return destination;

            case 2:
                destination[destOffset] = ALPHABET[(inBuff >>> 18)];
                destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f];
                destination[destOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3f];
                destination[destOffset + 3] = EQUALS_SIGN;
                return destination;

            case 1:
                destination[destOffset] = ALPHABET[(inBuff >>> 18)];
                destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f];
                destination[destOffset + 2] = EQUALS_SIGN;
                destination[destOffset + 3] = EQUALS_SIGN;
                return destination;

            default:
                return destination;
        }   // end switch
    }   // end encode3to4


    /**
     * Serializes an object and returns the Base64-encoded
     * version of that serialized object. If the object
     * cannot be serialized or there is another error,
     * the method will return <tt>null</tt>.
     *
     * @param serializableObject The object to encode
     * @return The Base64-encoded object
     * @since 1.4
     */
    public static String encodeObject(java.io.Serializable serializableObject)
    {
     
        java.io.ByteArrayOutputStream baos = null;
        java.io.OutputStream b64os = null;
        java.io.ObjectOutputStream oos = null;

        try
        {
            baos = new java.io.ByteArrayOutputStream();
            b64os = new OutputStream(baos, Base64.ENCODE);
            oos = new java.io.ObjectOutputStream(b64os);

            oos.writeObject(serializableObject);
        }   // end try
        catch (java.io.IOException e)
        {
           

            e.printStackTrace();
            return null;
        }   // end catch
        finally
        {
            try
            {
                oos.close();
                b64os.close();
                baos.close();
            }
            catch (Exception e)
            {
            }
        }   // end finally

        return new String(baos.toByteArray());
    }   // end encode


    /**
     * Encodes a byte array into Base64 notation.
     * Equivalen to calling
     * <code>encodeBytes( source, 0, source.length )</code>
     *
     * @param source The data to convert
     * @since 1.4
     */
    public static String encodeBytes(byte[] source)
    {

        return encodeBytes(source, 0, source.length);
    }   // end encodeBytes


    /**
     * Encodes a byte array into Base64 notation.
     *
     * @param source The data to convert
     * @param off Offset in array where conversion should begin
     * @param len Length of data to convert
     * @since 1.4
     */
    public static String encodeBytes(byte[] source, int off, int len)
    {

        int len43 = len * 4 / 3;
        byte[] outBuff = new byte[(len43)                      // Main 4:3
                + ((len % 3) > 0 ? 4 : 0)      // Account for padding
                + (len43 / MAX_LINE_LENGTH)]; // New lines
        int d = 0;
        int e = 0;
        int len2 = len - 2;
        int lineLength = 0;
        for (; d < len2; d += 3, e += 4)
        {
            encode3to4(source, d, 3, outBuff, e);

            lineLength += 4;
            if (lineLength == MAX_LINE_LENGTH)
            {
                outBuff[e + 4] = NEW_LINE;
                e++;
                lineLength = 0;
            }   // end if: end of line
        }   // en dfor: each piece of array

        if (d < len)
        {
            encode3to4(source, d, len - d, outBuff, e);
            e += 4;
        }   // end if: some padding needed

        return new String(outBuff, 0, e);
    }   // end encodeBytes


    /**
     * Encodes a string in Base64 notation with line breaks
     * after every 75 Base64 characters.
     *
     * @param s the string to encode
     * @return the encoded string
     * @since 1.3
     */
    public static String encodeString(String s)
    {
        return encodeBytes(s.getBytes());
    }   // end encodeString




/* ********  D E C O D I N G   M E T H O D S  ******** */


    /**
     * Decodes the first four bytes of array <var>fourBytes</var>
     * and returns an array up to three bytes long with the
     * decoded values.
     *
     * @param fourBytes the array with Base64 content
     * @return array with decoded values
     * @since 1.3
     */
    private static byte[] decode4to3(byte[] fourBytes)
    {

        byte[] outBuff1 = new byte[3];
        int count = decode4to3(fourBytes, 0, outBuff1, 0);
        byte[] outBuff2 = new byte[count];

        for (int i = 0; i < count; i++)
            outBuff2[i] = outBuff1[i];

        return outBuff2;
    }


    /**
     * Decodes four bytes from array <var>source</var>
     * and writes the resulting bytes (up to three of them)
     * to <var>destination</var>.
     * The source and destination arrays can be manipulated
     * anywhere along their length by specifying
     * <var>srcOffset</var> and <var>destOffset</var>.
     * This method does not check to make sure your arrays
     * are large enough to accomodate <var>srcOffset</var> + 4 for
     * the <var>source</var> array or <var>destOffset</var> + 3 for
     * the <var>destination</var> array.
     * This method returns the actual number of bytes that
     * were converted from the Base64 encoding.
     *
     *
     * @param source the array to convert
     * @param srcOffset the index where conversion begins
     * @param destination the array to hold the conversion
     * @param destOffset the index where output will be put
     * @return the number of decoded bytes converted
     * @since 1.3
     */
    private static int decode4to3(byte[] source, int srcOffset, byte[] destination, int destOffset)
    {

        // Example: Dk==
        if (source[srcOffset + 2] == EQUALS_SIGN)
        {
            int outBuff = ((DECODABET[source[srcOffset]] << 24) >>> 6)
                    | ((DECODABET[source[srcOffset + 1]] << 24) >>> 12);

            destination[destOffset] = (byte)(outBuff >>> 16);
            return 1;
        }

        // Example: DkL=
        else if (source[srcOffset + 3] == EQUALS_SIGN)
        {
            int outBuff = ((DECODABET[source[srcOffset]] << 24) >>> 6)
                    | ((DECODABET[source[srcOffset + 1]] << 24) >>> 12)
                    | ((DECODABET[source[srcOffset + 2]] << 24) >>> 18);

            destination[destOffset] = (byte)(outBuff >>> 16);
            destination[destOffset + 1] = (byte)(outBuff >>> 8);
            return 2;
        }

        // Example: DkLE
        else
        {
            int outBuff = ((DECODABET[source[srcOffset]] << 24) >>> 6)
                    | ((DECODABET[source[srcOffset + 1]] << 24) >>> 12)
                    | ((DECODABET[source[srcOffset + 2]] << 24) >>> 18)
                    | ((DECODABET[source[srcOffset + 3]] << 24) >>> 24);

            destination[destOffset] = (byte)(outBuff >> 16);
            destination[destOffset + 1] = (byte)(outBuff >> 8);
            destination[destOffset + 2] = (byte)(outBuff);
            return 3;
        }
    }   // end decodeToBytes


    /**
     * Decodes data from Base64 notation.
     *
     * @param s the string to decode
     * @return the decoded data
     * @since 1.4
     */
    public static byte[] decode(String s)
    {

        byte[] bytes = s.getBytes();
        return decode(bytes, 0, bytes.length);
    }   // end decode


    /**
     * Decodes data from Base64 notation and
     * returns it as a string.
     * Equivalent to calling
     * <code>new String( decode( s ) )</code>
     *
     * @param s the string to decode
     * @return The data as a string
     * @since 1.4
     */
    public static String decodeToString(String s)
    {

        return new String(decode(s));
    }   // end decodeToString


    /**
     * Attempts to decode Base64 data and deserialize a Java
     * Object within. Returns <tt>null</tt> if there was an error.
     *
     * @param encodedObject The Base64 data to decode
     * @return The decoded and deserialized object
     * @since 1.4
     */
    public static Object decodeToObject(String encodedObject)
    {

        byte[] objBytes = decode(encodedObject);

        java.io.ByteArrayInputStream bais = null;
        java.io.ObjectInputStream ois = null;

        try
        {
            bais = new java.io.ByteArrayInputStream(objBytes);
            ois = new java.io.ObjectInputStream(bais);

            return ois.readObject();
        }   // end try
        catch (java.io.IOException e)
        {

            e.printStackTrace();
            return null;
        }   // end catch
        catch (ClassNotFoundException e)
        {

            e.printStackTrace();
            return null;
        }   // end catch
        finally
        {
            try
            {
                bais.close();
                ois.close();
            }
            catch (Exception e)
            {
            }
        }   // end finally
    }   // end decodeObject


    /**
     * Decodes Base64 content in byte array format and returns
     * the decoded byte array.
     *
     * @param source The Base64 encoded data
     * @param off    The offset of where to begin decoding
     * @param len    The length of characters to decode
     * @return decoded data
     * @since 1.3
     */
    public static byte[] decode(byte[] source, int off, int len)
    {

        int len34 = len * 3 / 4;
        byte[] outBuff = new byte[len34]; // Upper limit on size of output
        int outBuffPosn = 0;

        byte[] b4 = new byte[4];
        int b4Posn = 0;
        int i = 0;
        byte sbiCrop = 0;
        byte sbiDecode = 0;
        for (i = 0; i < len; i++)
        {
            sbiCrop = (byte)(source[i] & 0x7f); // Only the low seven bits
            sbiDecode = DECODABET[sbiCrop];

            if (sbiDecode >= WHITE_SPACE_ENC) // White space, Equals sign or better
            {
                if (sbiDecode >= EQUALS_SIGN_ENC)
                {
                    b4[b4Posn++] = sbiCrop;
                    if (b4Posn > 3)
                    {
                        outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn);
                        b4Posn = 0;

                        // If that was the equals sign, break out of 'for' loop
                        if (sbiCrop == EQUALS_SIGN)
                            break;
                    }   // end if: quartet built

                }   // end if: equals sign or better

            }   // end if: white space, equals sign or better
            else
            {
                System.err.println("Bad Base64 input character at " + i + ": " + source[i] + "(decimal)");
                return null;
            }   // end else:
        }   // each input character

        byte[] out = new byte[outBuffPosn];
        System.arraycopy(outBuff, 0, out, 0, outBuffPosn);
        return out;
    }   // end decode




    /* ********  I N N E R   C L A S S   I N P U T S T R E A M  ******** */



    /**
     * A {@link Base64.InputStream} will read data from another
     * {@link java.io.InputStream}, given in the constructor,
     * and encode/decode to/from Base64 notation on the fly.
     *
     * @see Base64
     * @see java.io.FilterInputStream
     * @since 1.3
     */
    public static class InputStream extends java.io.FilterInputStream
    {
        private boolean encode;         // Encoding or decoding
        private int position;       // Current position in the buffer
        private byte[] buffer;         // Small buffer holding converted data
        private int bufferLength;   // Length of buffer (3 or 4)
        private int numSigBytes;    // Number of meaningful bytes in the buffer


        /**
         * Constructs a {@link Base64.InputStream} in DECODE mode.
         *
         * @param in the {@link java.io.InputStream} from which to read data.
         * @since 1.3
         */
        public InputStream(java.io.InputStream in)
        {
            this(in, Base64.DECODE);
        }   // end constructor


        /**
         * Constructs a {@link Base64.InputStream} in
         * either ENCODE or DECODE mode.
         *
         * @param in the {@link java.io.InputStream} from which to read data.
         * @param encode Conversion direction
         * @see Base64#ENCODE
         * @see Base64#DECODE
         * @since 1.3
         */
        public InputStream(java.io.InputStream in, boolean encode)
        {
            super(in);
            this.encode = encode;
            this.bufferLength = encode ? 4 : 3;
            this.buffer = new byte[bufferLength];
            this.position = -1;
        }   // end constructor

        /**
         * Reads enough of the input stream to convert
         * to/from Base64 and returns the next byte.
         *
         * @return next byte
         * @since 1.3
         */
        public int read() throws java.io.IOException
        {
            // Do we need to get data?
            if (position < 0)
            {
                if (encode)
                {
                    byte[] b3 = new byte[3];
                    numSigBytes = 0;
                    for (int i = 0; i < 3; i++)
                    {
                        try
                        {
                            int b = in.read();

                            // If end of stream, b is -1.
                            if (b >= 0)
                            {
                                b3[i] = (byte)b;
                                numSigBytes++;
                            }   // end if: not end of stream

                        }   // end try: read
                        catch (java.io.IOException e)
                        {

                            // Only a problem if we got no data at all.
                            if (i == 0)
                                throw e;

                        }   // end catch
                    }   // end for: each needed input byte

                    if (numSigBytes > 0)
                    {
                        encode3to4(b3, 0, numSigBytes, buffer, 0);
                        position = 0;
                    }   // end if: got data
                }   // end if: encoding

                // Else decoding
                else
                {
                    byte[] b4 = new byte[4];
                    int i = 0;
                    for (i = 0; i < 4; i++)
                    {
                        int b = 0;
                        do
                        {
                            b = in.read();
                        }
                        while (b >= 0 && DECODABET[b & 0x7f] < WHITE_SPACE_ENC);

                        if (b < 0)
                            break; // Reads a -1 if end of stream

                        b4[i] = (byte)b;
                    }   // end for: each needed input byte

                    if (i == 4)
                    {
                        numSigBytes = decode4to3(b4, 0, buffer, 0);
                        position = 0;
                    }   // end if: got four characters

                }   // end else: decode
            }   // end else: get data

            // Got data?
            if (position >= 0)
            {
                // End of relevant data?
                if (position >= numSigBytes)
                    return -1;

                int b = buffer[position++];

                if (position >= bufferLength)
                    position = -1;

                return b;
            }   // end if: position >= 0

            // Else error
            else
                return -1;
        }   // end read


        /**
         * Calls {@link #read} repeatedly until the end of stream
         * is reached or <var>len</var> bytes are read.
         * Returns number of bytes read into array or -1 if
         * end of stream is encountered.
         *
         * @param dest array to hold values
         * @param off offset for array
         * @param len max number of bytes to read into array
         * @return bytes read into array or -1 if end of stream is encountered.
         * @since 1.3
         */
        public int read(byte[] dest, int off, int len) throws java.io.IOException
        {
            int i;
            int b;
            for (i = 0; i < len; i++)
            {
                b = read();

                if (b < 0)
                    return -1;

                dest[off + i] = (byte)b;
            }   // end for: each byte read
            return i;
        }   // end read

    }   // end inner class InputStream






    /* ********  I N N E R   C L A S S   O U T P U T S T R E A M  ******** */



    /**
     * A {@link Base64.OutputStream} will write data to another
     * {@link java.io.OutputStream}, given in the constructor,
     * and encode/decode to/from Base64 notation on the fly.
     *
     * @see Base64
     * @see java.io.FilterOutputStream
     * @since 1.3
     */
    public static class OutputStream extends java.io.FilterOutputStream
    {


        private boolean encode;
        private int position;
        private byte[] buffer;
        private int bufferLength;
        private int lineLength;


        /**
         * Constructs a {@link Base64.OutputStream} in ENCODE mode.
         *
         * @param out the {@link java.io.OutputStream} to which data will be written.
         * @since 1.3
         */
        public OutputStream(java.io.OutputStream out)
        {
            this(out, Base64.ENCODE);
        }   // end constructor


        /**
         * Constructs a {@link Base64.OutputStream} in
         * either ENCODE or DECODE mode.
         *
         * @param out the {@link java.io.OutputStream} to which data will be written.
         * @param encode Conversion direction
         * @see Base64#ENCODE
         * @see Base64#DECODE
         * @since 1.3
         */
        public OutputStream(java.io.OutputStream out, boolean encode)
        {
            super(out);
            this.encode = encode;
            this.bufferLength = encode ? 3 : 4;
            this.buffer = new byte[bufferLength];
            this.position = 0;
            this.lineLength = 0;
        }   // end constructor


        /**
         * Writes the byte to the output stream after
         * converting to/from Base64 notation.
         * When encoding, bytes are buffered three
         * at a time before the output stream actually
         * gets a write() call.
         * When decoding, bytes are buffered four
         * at a time.
         *
         * @param theByte the byte to write
         * @since 1.3
         */
        public void write(int theByte) throws java.io.IOException
        {
            buffer[position++] = (byte)theByte;
            if (position >= bufferLength)
            {
                if (encode)
                {
                    out.write(Base64.encode3to4(buffer, bufferLength));

                    lineLength += 4;
                    if (lineLength >= MAX_LINE_LENGTH)
                    {
                        out.write(NEW_LINE);
                        lineLength = 0;
                    }   // end if: end o fline
                }   // end if: encoding
                else
                    out.write(Base64.decode4to3(buffer));

                position = 0;
            }   // end if: convert and flush
        }   // end write


        /**
         * Calls {@link #write} repeatedly until <var>len</var>
         * bytes are written.
         *
         * @param theBytes array from which to read bytes
         * @param off offset for array
         * @param len max number of bytes to read into array
         * @since 1.3
         */
        public void write(byte[] theBytes, int off, int len) throws java.io.IOException
        {

            for (int i = 0; i < len; i++)
            {
                write(theBytes[off + i]);
            }   // end for: each byte written

        }   // end write


        /**
         * Appropriately pads Base64 notation when encoding
         * or throws an exception if Base64 input is not
         * properly padded when decoding.
         *
         * @since 1.3
         */
        public void flush() throws java.io.IOException
        {

            if (position > 0)
            {
                if (encode)
                {
                    out.write(Base64.encode3to4(buffer, position));
                }   // end if: encoding
                else
                {
                    throw new java.io.IOException("Base64 input not properly padded.");
                }   // end else: decoding
            }   // end if: buffer partially full

            super.flush();
            out.flush();
        }   // end flush


        /**
         * Flushes and closes stream.
         *
         * @since 1.3
         */
        public void close() throws java.io.IOException
        {

            this.flush();

            super.close();
            out.close();

            buffer = null;
            out = null;
        }   // end close

    }   // end inner class OutputStream
}   // end class Base64

   
    
    
    
  








Related examples in the same category

1.BASE64 Decoder Stream
2.BASE64 Encoder Stream from Sun Microsystems
3.Base64 Character decoder as specified in RFC1113.
4.Base64 Character encoder as specified in RFC1113.
5.Performs Base-64 decoding on an underlying stream.
6.Class encodes the bytes written to the OutPutStream to a Base64 encoded string.
7.BASE64 Decoder Stream from Sun Microsystems
8.BASE64 Encoder Stream
9.Decode a BASE64 encoded input stream to some output stream
10.Hex dump
11.Dumps data in hexadecimal format
12.Apply a ASCII Hex encoding to the stream
13.Base64 Codec
14.Base64 provides Base64 encoding/decoding of strings and streams
15.Base64 - encode/decode data using the Base64 encoding scheme
16.Base64 from Eric Glass jcifs at samba dot org