Author: scolebourne Date: Fri Dec 29 05:50:34 2006 New Revision: 491007 URL: http://svn.apache.org/viewvc?view=rev&rev=491007 Log: IO-97 - ByteArrayOutputStream performance enhancements, from Holger Hoffstatte
Modified: jakarta/commons/proper/io/trunk/RELEASE-NOTES.txt jakarta/commons/proper/io/trunk/src/java/org/apache/commons/io/output/ByteArrayOutputStream.java jakarta/commons/proper/io/trunk/src/test/org/apache/commons/io/output/ByteArrayOutputStreamTestCase.java Modified: jakarta/commons/proper/io/trunk/RELEASE-NOTES.txt URL: http://svn.apache.org/viewvc/jakarta/commons/proper/io/trunk/RELEASE-NOTES.txt?view=diff&rev=491007&r1=491006&r2=491007 ============================================================================== --- jakarta/commons/proper/io/trunk/RELEASE-NOTES.txt (original) +++ jakarta/commons/proper/io/trunk/RELEASE-NOTES.txt Fri Dec 29 05:50:34 2006 @@ -189,6 +189,9 @@ - NullReader - New reader that emulates a reader of a specified size +- ByteArrayOutputStream [IO-97] + - Performance enhancements + Feedback -------- Modified: jakarta/commons/proper/io/trunk/src/java/org/apache/commons/io/output/ByteArrayOutputStream.java URL: http://svn.apache.org/viewvc/jakarta/commons/proper/io/trunk/src/java/org/apache/commons/io/output/ByteArrayOutputStream.java?view=diff&rev=491007&r1=491006&r2=491007 ============================================================================== --- jakarta/commons/proper/io/trunk/src/java/org/apache/commons/io/output/ByteArrayOutputStream.java (original) +++ jakarta/commons/proper/io/trunk/src/java/org/apache/commons/io/output/ByteArrayOutputStream.java Fri Dec 29 05:50:34 2006 @@ -44,14 +44,23 @@ * deprecated toString(int) method that has been ignored. * * @author <a href="mailto:[EMAIL PROTECTED]">Jeremias Maerki</a> + * @author Holger Hoffstatte * @version $Id$ */ public class ByteArrayOutputStream extends OutputStream { + /** A singleton empty byte array. */ + private static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; + + /** The list of buffers, which grows and never reduces. */ private List buffers = new ArrayList(); + /** The index of the current buffer. */ private int currentBufferIndex; + /** The total count of bytes in all the filled buffers. */ private int filledBufferSum; + /** The current buffer. */ private byte[] currentBuffer; + /** The total count of bytes written. */ private int count; /** @@ -85,7 +94,7 @@ * @return the buffer */ private byte[] getBuffer(int index) { - return (byte[])buffers.get(index); + return (byte[]) buffers.get(index); } /** @@ -123,7 +132,7 @@ /** * @see java.io.OutputStream#write(byte[], int, int) */ - public synchronized void write(byte[] b, int off, int len) { + public void write(byte[] b, int off, int len) { if ((off < 0) || (off > b.length) || (len < 0) @@ -133,34 +142,40 @@ } else if (len == 0) { return; } - int newcount = count + len; - int remaining = len; - int inBufferPos = count - filledBufferSum; - while (remaining > 0) { - int part = Math.min(remaining, currentBuffer.length - inBufferPos); - System.arraycopy(b, off + len - remaining, currentBuffer, inBufferPos, part); - remaining -= part; - if (remaining > 0) { - needNewBuffer(newcount); - inBufferPos = 0; + synchronized (this) { + int newcount = count + len; + int remaining = len; + int inBufferPos = count - filledBufferSum; + while (remaining > 0) { + int part = Math.min(remaining, currentBuffer.length - inBufferPos); + System.arraycopy(b, off + len - remaining, currentBuffer, inBufferPos, part); + remaining -= part; + if (remaining > 0) { + needNewBuffer(newcount); + inBufferPos = 0; + } } + count = newcount; } - count = newcount; } /** - * Calls the write(byte[]) method. - * * @see java.io.OutputStream#write(int) */ public synchronized void write(int b) { - write(new byte[] {(byte)b}, 0, 1); + int inBufferPos = count - filledBufferSum; + if (inBufferPos == currentBuffer.length) { + needNewBuffer(count + 1); + inBufferPos = 0; + } + currentBuffer[inBufferPos] = (byte) b; + count++; } /** * @see java.io.ByteArrayOutputStream#size() */ - public int size() { + public synchronized int size() { return count; } @@ -216,8 +231,11 @@ */ public synchronized byte[] toByteArray() { int remaining = count; + if (remaining == 0) { + return EMPTY_BYTE_ARRAY; + } + byte newbuf[] = new byte[remaining]; int pos = 0; - byte newbuf[] = new byte[count]; for (int i = 0; i < buffers.size(); i++) { byte[] buf = getBuffer(i); int c = Math.min(buf.length, remaining); Modified: jakarta/commons/proper/io/trunk/src/test/org/apache/commons/io/output/ByteArrayOutputStreamTestCase.java URL: http://svn.apache.org/viewvc/jakarta/commons/proper/io/trunk/src/test/org/apache/commons/io/output/ByteArrayOutputStreamTestCase.java?view=diff&rev=491007&r1=491006&r2=491007 ============================================================================== --- jakarta/commons/proper/io/trunk/src/test/org/apache/commons/io/output/ByteArrayOutputStreamTestCase.java (original) +++ jakarta/commons/proper/io/trunk/src/test/org/apache/commons/io/output/ByteArrayOutputStreamTestCase.java Fri Dec 29 05:50:34 2006 @@ -104,10 +104,12 @@ //First three writes written = writeData(baout, ref, new int[] {4, 10, 22}); + assertEquals(36, written); checkStreams(baout, ref); //Another two writes to see if there are any bad effects after toByteArray() written = writeData(baout, ref, new int[] {20, 12}); + assertEquals(32, written); checkStreams(baout, ref); //Now reset the streams @@ -116,6 +118,7 @@ //Test again to see if reset() had any bad effects written = writeData(baout, ref, new int[] {5, 47, 33, 60, 1, 0, 8}); + assertEquals(155, written); checkStreams(baout, ref); //Write the commons Byte[]OutputStream to a java.io.Byte[]OutputStream @@ -130,6 +133,11 @@ String baoutString = baout.toString("ASCII"); String refString = ref.toString("ASCII"); assertEquals("ASCII decoded String must be equal", refString, baoutString); + + //Make sure that empty ByteArrayOutputStreams really don't create garbage + //on toByteArray() + assertSame(new ByteArrayOutputStream().toByteArray(), + new ByteArrayOutputStream().toByteArray()); } } --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]