A speedy implementation of ByteArrayOutputStream. : ByteArrayOutputStream « File « Java Tutorial

Java Tutorial
1. Language
2. Data Type
3. Operators
4. Statement Control
5. Class Definition
6. Development
7. Reflection
8. Regular Expressions
9. Collections
10. Thread
11. File
12. Generics
13. I18N
14. Swing
15. Swing Event
16. 2D Graphics
17. SWT
18. SWT 2D Graphics
19. Network
20. Database
21. Hibernate
22. JPA
23. JSP
24. JSTL
25. Servlet
26. Web Services SOA
27. EJB3
28. Spring
29. PDF
30. Email
31. J2ME
32. J2EE Application
33. XML
34. Design Pattern
35. Log
36. Security
37. Apache Common
38. Ant
39. JUnit
Java
Java Source Code / Java Documentation
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Tutorial » File » ByteArrayOutputStream 
11. 24. 2. A speedy implementation of ByteArrayOutputStream.
/*
 * Copyright (c) 2002-2003 by OpenSymphony
 * All rights reserved.
 */

import java.io.IOException;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.io.Writer;
import java.util.Iterator;
import java.util.LinkedList;


/**
 * A speedy implementation of ByteArrayOutputStream. It's not synchronized, and it
 * does not copy buffers when it's expanded. There's also no copying of the internal buffer
 * if it's contents is extracted with the writeTo(stream) method.
 *
 @author Rickard ?berg
 @author Brat Baker (Atlassian)
 @author Alexey
 @version $Date: 2008-01-19 10:09:56 +0800 (Sat, 19 Jan 2008) $ $Id: FastByteArrayOutputStream.java 3000 2008-01-19 02:09:56Z tm_jee $
 */
public class FastByteArrayOutputStream extends OutputStream {

    // Static --------------------------------------------------------
    private static final int DEFAULT_BLOCK_SIZE = 8192;


    private LinkedList buffers;

    // Attributes ----------------------------------------------------
    // internal buffer
    private byte[] buffer;

    // is the stream closed?
    private boolean closed;
    private int blockSize;
    private int index;
    private int size;


    // Constructors --------------------------------------------------
    public FastByteArrayOutputStream() {
        this(DEFAULT_BLOCK_SIZE);
    }

    public FastByteArrayOutputStream(int aSize) {
        blockSize = aSize;
        buffer = new byte[blockSize];
    }


    public int getSize() {
        return size + index;
    }

    public void close() {
        closed = true;
    }

    public byte[] toByteArray() {
        byte[] data = new byte[getSize()];

        // Check if we have a list of buffers
        int pos = 0;

        if (buffers != null) {
            Iterator iter = buffers.iterator();

            while (iter.hasNext()) {
                byte[] bytes = (byte[]) iter.next();
                System.arraycopy(bytes, 0, data, pos, blockSize);
                pos += blockSize;
            }
        }

        // write the internal buffer directly
        System.arraycopy(buffer, 0, data, pos, index);

        return data;
    }

    public String toString() {
        return new String(toByteArray());
    }

    // OutputStream overrides ----------------------------------------
    public void write(int datumthrows IOException {
        if (closed) {
            throw new IOException("Stream closed");
        else {
            if (index == blockSize) {
                addBuffer();
            }

            // store the byte
            buffer[index++(bytedatum;
        }
    }

    public void write(byte[] data, int offset, int lengththrows IOException {
        if (data == null) {
            throw new NullPointerException();
        else if ((offset < 0|| ((offset + length> data.length|| (length < 0)) {
            throw new IndexOutOfBoundsException();
        else if (closed) {
            throw new IOException("Stream closed");
        else {
            if ((index + length> blockSize) {
                int copyLength;

                do {
                    if (index == blockSize) {
                        addBuffer();
                    }

                    copyLength = blockSize - index;

                    if (length < copyLength) {
                        copyLength = length;
                    }

                    System.arraycopy(data, offset, buffer, index, copyLength);
                    offset += copyLength;
                    index += copyLength;
                    length -= copyLength;
                while (length > 0);
            else {
                // Copy in the subarray
                System.arraycopy(data, offset, buffer, index, length);
                index += length;
            }
        }
    }

    // Public
    public void writeTo(OutputStream outthrows IOException {
        // Check if we have a list of buffers
        if (buffers != null) {
            Iterator iter = buffers.iterator();

            while (iter.hasNext()) {
                byte[] bytes = (byte[]) iter.next();
                out.write(bytes, 0, blockSize);
            }
        }

        // write the internal buffer directly
        out.write(buffer, 0, index);
    }

    public void writeTo(RandomAccessFile outthrows IOException {
        // Check if we have a list of buffers
        if (buffers != null) {
            Iterator iter = buffers.iterator();

            while (iter.hasNext()) {
                byte[] bytes = (byte[]) iter.next();
                out.write(bytes, 0, blockSize);
            }
        }

        // write the internal buffer directly
        out.write(buffer, 0, index);
    }

    public void writeTo(Writer out, String encodingthrows IOException {
        /*
          There is design tradeoff between being fast, correct and using too much memory when decoding bytes to strings.

         The rules are thus :

         1. if there is only one buffer then its a simple String conversion

              REASON : Fast!!!

         2. uses full buffer allocation annd System.arrayCopy() to smooosh together the bytes
              and then use String conversion

              REASON : Fast at the expense of a known amount of memory (eg the used memory * 2)
        */
        if (buffers != null)
        {
            // RULE 2 : a balance between using some memory and speed
            writeToViaSmoosh(out, encoding);
        }
        else
        {
            // RULE 1 : fastest!
            writeToViaString(out, encoding);
        }
    }

    /**
     * This can <b>ONLY</b> be called if there is only a single buffer to write, instead
     * use {@link #writeTo(java.io.Writer, String)}, which auto detects if
     {@link #writeToViaString(java.io.Writer, String)} is to be used or
     {@link #writeToViaSmoosh(java.io.Writer, String)}.
     *
     @param out      the JspWriter
     @param encoding the encoding
     @throws IOException
     */
    void writeToViaString(Writer out, String encodingthrows IOException
    {
        byte[] bufferToWrite = buffer; // this is always the last buffer to write
        int bufferToWriteLen = index;  // index points to our place in the last buffer
        writeToImpl(out, encoding, bufferToWrite, bufferToWriteLen);
    }

    /**
     * This is recommended to be used where there's more than 1 buffer to write, instead
     * use {@link #writeTo(java.io.Writer, String)} which auto detects if
     {@link #writeToViaString(java.io.Writer, String)} is to be used or
     {@link #writeToViaSmoosh(java.io.Writer, String)}.
     
     @param out
     @param encoding
     @throws IOException
     */
    void writeToViaSmoosh(Writer out, String encodingthrows IOException
    {
        byte[] bufferToWrite = toByteArray();
        int bufferToWriteLen = bufferToWrite.length;
        writeToImpl(out, encoding, bufferToWrite, bufferToWriteLen);
    }

    /**
     * Write <code>bufferToWriteLen</code> of bytes from <code>bufferToWrite</code> to
     * <code>out</code> encoding it at the same time.
     
     @param out
     @param encoding
     @param bufferToWrite
     @param bufferToWriteLen
     @throws IOException
     */
    private void writeToImpl(Writer out, String encoding, byte[] bufferToWrite, int bufferToWriteLen)
            throws IOException
    {
        String writeStr;
        if (encoding != null)
        {
            writeStr = new String(bufferToWrite, 0, bufferToWriteLen, encoding);
        }
        else
        {
            writeStr = new String(bufferToWrite, 0, bufferToWriteLen);
        }
        out.write(writeStr);
    }

    /**
     * Create a new buffer and store the
     * current one in linked list
     */
    protected void addBuffer() {
        if (buffers == null) {
            buffers = new LinkedList();
        }

        buffers.addLast(buffer);

        buffer = new byte[blockSize];
        size += index;
        index = 0;
    }
}
////////////////////////////


import java.io.IOException;
import javax.servlet.jsp.JspWriter;

/**
 * A test class for {@link webwork.util.FastByteArrayOutputStream}
 *
 @author Brad Baker (Atlassian)
 @since $Date$ $Id$
 */
public class FastByteArrayOutputStreamTestCase extends AbstractEncodingTestCase
{

    public void testLatinCharsets() throws Exception
    {
        assertEncoding(ASCII_TEXT, LATIN);
        assertEncoding(ASCII_TEXT, ASCII);
    }

    public void testRussianCharsets() throws Exception
    {
        assertEncoding(RUSSIAN_DESC_SHORT, KOI8_R);
        assertEncoding(RUSSIAN_DESC1, KOI8_R);

        assertEncoding(RUSSIAN_DESC_SHORT, WINDOWS_CYRILLIC);
        assertEncoding(RUSSIAN_DESC1, WINDOWS_CYRILLIC);
    }

    public void testUnicodeCharsets() throws Exception
    {
        String[] testStrs = {ASCII_TEXT_SHORT, ASCII_TEXT, RUSSIAN_DESC_SHORT, RUSSIAN_DESC1, CHINESE_TIMETRACKING, HUNGRIAN_APPLET_PROBLEM, };
        String[] encodings = UTF_8, UTF_16, UBIG_ENDIAN, ULITTLE_ENDIAN, UBIG_ENDIAN_UNMARKED, ULITTLE_ENDIAN_UNMARKED };

        assertEncodings(testStrs, encodings);
    }

    protected void implementEncodingTest(final String srcStr, final String encoding, final int bufferSize)
            throws Exception
    {
        FastByteArrayOutputStream bout = new FastByteArrayOutputStream(bufferSize);

        byte[] bytes = srcStr.getBytes(encoding);
        bout.write(bytes);

        JspWriter writer = new StringCapturingJspWriter();
        bout.writeTo(writer, encoding);

        String actualStr = writer.toString();
        String expectedStr = new String(bytes, encoding);
        assertTheyAreEqual(expectedStr, actualStr, encoding);
    }


    /**
     * Before it was changed to use {@link java.nio.charset.CharsetDecoder} is took an this time
     * <p/>
     * Total Call Time = 1112.0ms
     * Average Call Time = 0.001112ms
     * <p/>
     * Now with the change it takes this time
     * <p/>
     * <p/>
     * The idea is that it did not get significantly worse in performance
     *
     @throws IOException
     */
    public void testPerformanceOfWriteToJspWriter() throws IOException
    {
        final String NINEK_STR = makeRoughly(ASCII, * K);
        final String FIFTYK_STR = makeRoughly(ASCII, 50 * K);
        final String ONEHUNDREDK_STR = makeRoughly(ASCII, 100 * K);

        testPerformanceOfWriteToJspWriter(new TextSource()
        {
            public String getDesc()
            {
                return "With < than 8K of data";
            }

            public String getText(final int times)
            {
                return ASCII_TEXT;
            }
        });

        testPerformanceOfWriteToJspWriter(new TextSource()
        {
            public String getDesc()
            {
                return "With > than 8K of data";
            }

            public String getText(final int times)
            {
                return NINEK_STR;
            }
        });

        testPerformanceOfWriteToJspWriter(new TextSource()
        {
            public String getDesc()
            {
                return "With a 2/3 mix of small data and 1/3 > 8K of data";
            }

            public String getText(final int times)
            {
                if (times % == 0)
                {
                    return NINEK_STR;
                }
                return ASCII_TEXT;
            }
        });

        testPerformanceOfWriteToJspWriter(new TextSource()
        {
            public String getDesc()
            {
                return "With a 1/2 mix of small data and 1/2 > 8K of data";
            }

            public String getText(final int times)
            {
                if (times % == 0)
                {
                    return NINEK_STR;
                }
                return ASCII_TEXT;
            }
        });

        testPerformanceOfWriteToJspWriter(new TextSource()
        {
            public String getDesc()
            {
                return "With 50K of data";
            }

            public String getText(final int times)
            {
                return FIFTYK_STR;
            }
        });

        testPerformanceOfWriteToJspWriter(new TextSource()
        {
            public String getDesc()
            {
                return "With 100K of data";
            }

            public String getText(final int times)
            {
                return ONEHUNDREDK_STR;
            }
        });


    }

    
    public void testPerformanceOfWriteToJspWriter(TextSource textSourcethrows IOException
    {
        NoopJspWriter noopJspWriter = new NoopJspWriter();
        String[] methods = {
                "writeTo (using hueristics)",
                "writeToViaSmoosh",
        };

        System.out.println(textSource.getDesc());
        System.out.println();
        float bestTime = Float.MAX_VALUE;
        String bestMethod = methods[0];
        for (int methodIndex = 0; methodIndex < methods.length; methodIndex++)
        {
            String method = methods[methodIndex];

            float totalTime = 0;
            final int MAX_TIMES = 10;
            final int MAX_ITERATIONS = 100;
            for (int times = 0; times < MAX_TIMES; times++)
            {
                String srcText = textSource.getText(times);
                for (int i = 0; i < MAX_ITERATIONS; i++)
                {
                    FastByteArrayOutputStream bout = new FastByteArrayOutputStream();
                    bout.write(srcText.getBytes(UTF_8));

                    // just time the JspWriter output. And let it warm u first as well
                    if (times > 3)
                    {
                        long then = System.currentTimeMillis();
                        switch (methodIndex)
                        {
                            case 0:
                                bout.writeTo(noopJspWriter, UTF_8);
                                break;
                            case 1:
                                bout.writeToViaSmoosh(noopJspWriter, UTF_8);
                                break;
                        }
                        long now = System.currentTimeMillis();
                        totalTime += (now - then);
                    }
                }
            }
            float avgTime = totalTime / MAX_TIMES / MAX_ITERATIONS;
            System.out.println(method + "  - Total Call Time = " + totalTime + "ms");
            System.out.println(method + " - Average Call Time = " + avgTime + "ms");
            System.out.println();

            if (avgTime < bestTime) {
                bestTime = avgTime;
                bestMethod = method;
            }
        }
        System.out.println(bestMethod + " was the best method - Average Call Time = " + bestTime + "ms");
        System.out.println("____________________\n");

    }

    interface TextSource
    {
        String getDesc();

        String getText(int times);
    }

    static class StringCapturingJspWriter extends NoopJspWriter
    {
        StringCapturingJspWriter()
        {
            super(true);
        }
    }


    static class NoopJspWriter extends JspWriter
    {
        final StringBuffer sb = new StringBuffer();
        final boolean capture;

        NoopJspWriter()
        {
            this(false);
        }

        NoopJspWriter(boolean capture)
        {
            super(0false);
            this.capture = capture;
        }

        NoopJspWriter(final int i, final boolean b)
        {
            super(i, b);
            this.capture = false;
        }

        public String toString()
        {
            return sb.toString();
        }

        public void clear() throws IOException
        {
        }

        public void clearBuffer() throws IOException
        {
        }

        public void close() throws IOException
        {
        }

        public void flush() throws IOException
        {
        }

        public int getRemaining()
        {
            return 0;
        }

        public void newLine() throws IOException
        {
        }

        public void print(final char cthrows IOException
        {
            if (capture)
            {
                sb.append(c);
            }
        }

        public void print(final double vthrows IOException
        {
            if (capture)
            {
                sb.append(v);
            }
        }

        public void print(final float vthrows IOException
        {
            if (capture)
            {
                sb.append(v);
            }
        }

        public void print(final int ithrows IOException
        {
            if (capture)
            {
                sb.append(i);
            }
        }

        public void print(final long lthrows IOException
        {
            if (capture)
            {
                sb.append(l);
            }
        }

        public void print(final Object othrows IOException
        {
            if (capture)
            {
                sb.append(o);
            }
        }

        public void print(final String sthrows IOException
        {
            if (capture)
            {
                sb.append(s);
            }
        }

        public void print(final boolean bthrows IOException
        {
            if (capture)
            {
                sb.append(b);
            }
        }

        public void print(final char[] charsthrows IOException
        {
            if (capture)
            {
                sb.append(chars);
            }
        }

        public void println() throws IOException
        {
            print('\n');
        }

        public void println(final char cthrows IOException
        {
            print(c);
            println();
        }

        public void println(final double vthrows IOException
        {
            print(v);
            println();
        }

        public void println(final float vthrows IOException
        {
            print(v);
            println();
        }

        public void println(final int ithrows IOException
        {
            print(i);
            println();
        }

        public void println(final long lthrows IOException
        {
            print(l);
            println();
        }

        public void println(final Object othrows IOException
        {
            print(o);
            println();
        }

        public void println(final String sthrows IOException
        {
            print(s);
            println();
        }

        public void println(final boolean bthrows IOException
        {
            print(b);
            println();
        }

        public void println(final char[] charsthrows IOException
        {
            print(chars);
            println();
        }

        public void write(final char cbuf[]final int off, final int lenthrows IOException
        {
            String s = new String(cbuf, off, len);
            print(s);
        }
    }
}
11. 24. ByteArrayOutputStream
11. 24. 1. ByteArrayOutputStream Demo
11. 24. 2. A speedy implementation of ByteArrayOutputStream.
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.