Java/File Input Output/ByteArrayOutputStream — различия между версиями
Admin (обсуждение | вклад) м (1 версия) |
|
(нет различий)
|
Текущая версия на 09:03, 1 июня 2010
Содержание
An unsynchronized version of java.io.ByteArrayOutputStream
<source lang="java">
/* Copyright (C) 2003 Vladimir Roubtsov. All rights reserved.
* * This program and the accompanying materials are made available under * the terms of the Common Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/cpl-v10.html * * $Id: ByteArrayOStream.java,v 1.1.1.1 2004/05/09 16:57:52 vlad_r Exp $ */
import java.io.IOException; import java.io.OutputStream;
// ---------------------------------------------------------------------------- /**
* An unsynchronized version of java.io.ByteArrayOutputStream that can expose * the underlying byte array without a defensive clone and can also be converted* to a {@link ByteArrayIStream} without intermediate array copies.
* * All argument validation is disabled in release mode.<p> * * NOTE: copy-on-write not supported * * @author (C) 2001, Vlad Roubtsov */ public final class ByteArrayOStream extends OutputStream { // public: ................................................................ /** * Callee takes ownership of "buf". */ public ByteArrayOStream (final int initialCapacity) { m_buf = new byte [initialCapacity]; } public final void write2 (final int b1, final int b2) { final int pos = m_pos; final int capacity = pos + 2; byte [] mbuf = m_buf; final int mbuflen = mbuf.length; if (mbuflen < capacity) { final byte [] newbuf = new byte [Math.max (mbuflen << 1, capacity)]; if (pos < NATIVE_COPY_THRESHOLD) for (int i = 0; i < pos; ++ i) newbuf [i] = mbuf [i]; else System.arraycopy (mbuf, 0, newbuf, 0, pos); m_buf = mbuf = newbuf; } mbuf [pos] = (byte) b1; mbuf [pos + 1] = (byte) b2; m_pos = capacity; } public final void write3 (final int b1, final int b2, final int b3) { final int pos = m_pos; final int capacity = pos + 3; byte [] mbuf = m_buf; final int mbuflen = mbuf.length; if (mbuflen < capacity) { final byte [] newbuf = new byte [Math.max (mbuflen << 1, capacity)]; if (pos < NATIVE_COPY_THRESHOLD) for (int i = 0; i < pos; ++ i) newbuf [i] = mbuf [i]; else System.arraycopy (mbuf, 0, newbuf, 0, pos); m_buf = mbuf = newbuf; } mbuf [pos] = (byte) b1; mbuf [pos + 1] = (byte) b2; mbuf [pos + 2] = (byte) b3; m_pos = capacity; } public final void write4 (final int b1, final int b2, final int b3, final int b4) { final int pos = m_pos; final int capacity = pos + 4; byte [] mbuf = m_buf; final int mbuflen = mbuf.length; if (mbuflen < capacity) { final byte [] newbuf = new byte [Math.max (mbuflen << 1, capacity)]; if (pos < NATIVE_COPY_THRESHOLD) for (int i = 0; i < pos; ++ i) newbuf [i] = mbuf [i]; else System.arraycopy (mbuf, 0, newbuf, 0, pos); m_buf = mbuf = newbuf; } mbuf [pos] = (byte) b1; mbuf [pos + 1] = (byte) b2; mbuf [pos + 2] = (byte) b3; mbuf [pos + 3] = (byte) b4; m_pos = capacity; } public final void writeTo (final OutputStream out) throws IOException { out.write (m_buf, 0, m_pos); } // public final void readFully (final InputStream in) // throws IOException // { // while (true) // { // int chunk = in.available (); // // System.out.println ("available = " + chunk); // // // TODO: this case is handled poorly (on EOF) // if (chunk == 0) chunk = READ_CHUNK_SIZE; // // // read at least "available" bytes: extend the capacity as needed // // int free = m_buf.length - m_pos; // // final int read; // if (free > chunk) // { // // try reading more than "chunk" anyway: // read = in.read (m_buf, m_pos, free); // } // else // { // // extend the capacity to match "chunk": // { // System.out.println ("reallocation"); // final byte [] newbuf = new byte [m_pos + chunk]; // // if (m_pos < NATIVE_COPY_THRESHOLD) // for (int i = 0; i < m_pos; ++ i) newbuf [i] = m_buf [i]; // else // System.arraycopy (m_buf, 0, newbuf, 0, m_pos); // // m_buf = newbuf; // } // // read = in.read (m_buf, m_pos, chunk); // } // // if (read < 0) // break; // else // m_pos += read; // } // } // public final void addCapacity (final int extraCapacity) // { // final int pos = m_pos; // final int capacity = pos + extraCapacity; // byte [] mbuf = m_buf; // final int mbuflen = mbuf.length; // // if (mbuflen < capacity) // { // final byte [] newbuf = new byte [Math.max (mbuflen << 1, capacity)]; // // if (pos < NATIVE_COPY_THRESHOLD) // for (int i = 0; i < pos; ++ i) newbuf [i] = mbuf [i]; // else // System.arraycopy (mbuf, 0, newbuf, 0, pos); // // m_buf = newbuf; // } // } public final byte [] getByteArray () { return m_buf; } /** * * @return [result.length = size()] */ public final byte [] copyByteArray () { final int pos = m_pos; final byte [] result = new byte [pos]; final byte [] mbuf = m_buf; if (pos < NATIVE_COPY_THRESHOLD) for (int i = 0; i < pos; ++ i) result [i] = mbuf [i]; else System.arraycopy (mbuf, 0, result, 0, pos); return result; } public final int size () { return m_pos; } public final int capacity () { return m_buf.length; } /** * Does not reduce the current capacity. */ public final void reset () { m_pos = 0; } // OutputStream: public final void write (final int b) { final int pos = m_pos; final int capacity = pos + 1; byte [] mbuf = m_buf; final int mbuflen = mbuf.length; if (mbuflen < capacity) { final byte [] newbuf = new byte [Math.max (mbuflen << 1, capacity)]; if (pos < NATIVE_COPY_THRESHOLD) for (int i = 0; i < pos; ++ i) newbuf [i] = mbuf [i]; else System.arraycopy (mbuf, 0, newbuf, 0, pos); m_buf = mbuf = newbuf; } mbuf [pos] = (byte) b; m_pos = capacity; } public final void write (final byte [] buf, final int offset, final int length) { final int pos = m_pos; final int capacity = pos + length; byte [] mbuf = m_buf; final int mbuflen = mbuf.length; if (mbuflen < capacity) { final byte [] newbuf = new byte [Math.max (mbuflen << 1, capacity)]; if (pos < NATIVE_COPY_THRESHOLD) for (int i = 0; i < pos; ++ i) newbuf [i] = mbuf [i]; else System.arraycopy (mbuf, 0, newbuf, 0, pos); m_buf = mbuf = newbuf; } if (length < NATIVE_COPY_THRESHOLD) for (int i = 0; i < length; ++ i) mbuf [pos + i] = buf [offset + i]; else System.arraycopy (buf, offset, mbuf, pos, length); m_pos = capacity; } /** * Equivalent to {@link #reset()}. */ public final void close () { reset (); } // protected: ............................................................. // package: ............................................................... // private: ............................................................... private byte [] m_buf; private int m_pos; // private static final int READ_CHUNK_SIZE = 16 * 1024; private static final int NATIVE_COPY_THRESHOLD = 9; } // end of class // ---------------------------------------------------------------------------- </source>
A speedy implementation of ByteArrayOutputStream.
<source lang="java">
/*
* 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 datum) throws IOException { if (closed) { throw new IOException("Stream closed"); } else { if (index == blockSize) { addBuffer(); } // store the byte buffer[index++] = (byte) datum; } } public void write(byte[] data, int offset, int length) throws 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 out) throws 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 out) throws 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 encoding) throws 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 ONLY 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 encoding) throws 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 encoding) throws IOException { byte[] bufferToWrite = toByteArray(); int bufferToWriteLen = bufferToWrite.length; writeToImpl(out, encoding, bufferToWrite, bufferToWriteLen); } /** * WritebufferToWriteLen
of bytes frombufferToWrite
to *out
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, 9 * 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 % 3 == 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 % 2 == 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 textSource) throws 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(0, false); 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 c) throws IOException { if (capture) { sb.append(c); } } public void print(final double v) throws IOException { if (capture) { sb.append(v); } } public void print(final float v) throws IOException { if (capture) { sb.append(v); } } public void print(final int i) throws IOException { if (capture) { sb.append(i); } } public void print(final long l) throws IOException { if (capture) { sb.append(l); } } public void print(final Object o) throws IOException { if (capture) { sb.append(o); } } public void print(final String s) throws IOException { if (capture) { sb.append(s); } } public void print(final boolean b) throws IOException { if (capture) { sb.append(b); } } public void print(final char[] chars) throws IOException { if (capture) { sb.append(chars); } } public void println() throws IOException { print("\n"); } public void println(final char c) throws IOException { print(c); println(); } public void println(final double v) throws IOException { print(v); println(); } public void println(final float v) throws IOException { print(v); println(); } public void println(final int i) throws IOException { print(i); println(); } public void println(final long l) throws IOException { print(l); println(); } public void println(final Object o) throws IOException { print(o); println(); } public void println(final String s) throws IOException { print(s); println(); } public void println(final boolean b) throws IOException { print(b); println(); } public void println(final char[] chars) throws IOException { print(chars); println(); } public void write(final char cbuf[], final int off, final int len) throws IOException { String s = new String(cbuf, off, len); print(s); } }
}
</source>
Provides true Closable semantics ordinarily missing in a java.io.ByteArrayOutputStream
<source lang="java">
/* Copyright (c) 2001-2009, The HSQL Development Group
* All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the HSQL Development Group nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG, * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; /* $Id: ClosableByteArrayOutputStream.java 2946 2009-03-22 17:44:48Z fredt $ */ /**
* @todo - finer-grained synchronization to reduce average * potential monitor contention */
/**
* Provides true Closable semantics ordinarily missing in a * {@link java.io.ByteArrayOutputStream}. <p> * * Accumulates output in a byte array that automatically grows as needed.<p> * * Data is retrieved using toByteArray(), * toByteArrayInputStream(), toString() and * toString(encoding). <p> * * {@link #close() Closing} a ClosableByteArrayOutputStream prevents * further write operations, but all other operations may succeed until after * the first invocation of {@link #free() free()}.<p> * * Freeing a ClosableByteArrayOutputStream closes the stream and * releases the internal buffer, preventing successful invocation of all * operations, with the exception of size()<tt>, <tt>close(), * isClosed(), free() and isFreed(). <p> * * This class is especially useful when an accumulating output stream must be * handed off to an extenal client under contract that the stream should * exhibit true Closable behaviour in response both to internally tracked * events and to client invocation of the OutputStream.close() method. * * @author boucherb@users * @version 1.9.0 * @since 1.9.0 */
public class ClosableByteArrayOutputStream extends OutputStream {
/** * Data buffer. */ protected byte[] buf; /** * # of valid bytes in buffer. */ protected int count; /** * Whether this stream is closed. */ protected boolean closed; /** * Whether this stream is freed. */ protected boolean freed; /** * Creates a new output stream. <p> * * The buffer capacity is initially 32 bytes, though its size increases * if necessary. */ public ClosableByteArrayOutputStream() { this(32); } /** * Creates a new output stream with a buffer capacity of the specified * size, in bytes. * * @param size the initial size. * @exception IllegalArgumentException if size is negative. */ public ClosableByteArrayOutputStream(int size) throws IllegalArgumentException { if (size < 0) { throw new IllegalArgumentException("Negative initial size: " + size); // NOI18N } buf = new byte[size]; } /** * Writes the specified single byte. * * @param b the single byte to be written. * @throws java.io.IOException if an I/O error occurs. * In particular, an IOException may be thrown * if this output stream has been {@link #close() closed}. */ public synchronized void write(int b) throws IOException { checkClosed(); int newcount = count + 1; if (newcount > buf.length) { buf = copyOf(buf, Math.max(buf.length << 1, newcount)); } buf[count] = (byte) b; count = newcount; } /** * Writes the specified portion of the designated octet sequence. <p> * * @param b the data. * @param off the start offset in the data. * @param len the number of bytes to write. * @throws java.io.IOException if an I/O error occurs. * In particular, an IOException may be thrown * if this output stream has been {@link #close() closed}. */ public synchronized void write(byte b[], int off, int len) throws IOException { checkClosed(); if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0)) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return; } int newcount = count + len; if (newcount > buf.length) { buf = copyOf(buf, Math.max(buf.length << 1, newcount)); } System.arraycopy(b, off, buf, count, len); count = newcount; } /** * By default, does nothing. <p> * * @throws java.io.IOException if an I/O error occurs. * In particular, an IOException may be thrown * if this output stream has been {@link #close() closed}. */ public void flush() throws IOException { checkClosed(); } /** * Writes the complete contents of this stream"s accumulated data to the * specified output stream. <p> * * The operation occurs as if by calling out.write(buf, 0, count). * * @param out the output stream to which to write the data. * @throws java.io.IOException if an I/O error occurs. * In particular, an IOException may be thrown * if this output stream has been {@link #free() freed}. */ public synchronized void writeTo(OutputStream out) throws IOException { checkFreed(); out.write(buf, 0, count); } /** * Returns the current capacity of this stream"s data buffer. * * @return the length of the internal data array * @throws java.io.IOException if an I/O error occurs. * In particular, an IOException may be thrown * if this output stream has been {@link #free() freed}. */ public synchronized int capacity() throws IOException { checkFreed(); return buf.length; } /** * Resets the count field of this output stream to zero, so that * all currently accumulated data is effectively discarded. <p> * * Further write operations will reuse the allocated buffer space. <p> * * @see #count * @throws java.io.IOException if an I/O error occurs. * In particular, an IOException may be thrown * if this output stream has been {@link #close() closed}. */ public synchronized void reset() throws IOException { checkClosed(); count = 0; } /** * Attempts to reduce this stream"s capacity to its current size. <p> * * If the data buffer is larger than necessary to hold its current sequence * of bytes, then it may be resized to become more space efficient. * Calling this method may, but is not required to, affect the value * returned by a subsequent call to the {@link #capacity()} method. <p> * * @throws java.io.IOException if an I/O error occurs. * In particular, an IOException may be thrown * if this output stream has been {@link #free() freed}. */ public synchronized void trimToSize() throws IOException { checkFreed(); if (buf.length > count) { buf = copyOf(buf, count); } } /** * Retrieves a copy of this stream"s accumated data, as a byte array. * * @return a copy of this stream"s accumated data, as a byte array. * @see #size() * @throws java.io.IOException if an I/O error occurs. * In particular, an IOException may be thrown * if this output stream has been {@link #free() freed}. */ public synchronized byte[] toByteArray() throws IOException { checkFreed(); return copyOf(buf, count); } /** * Returns the current size of this stream"s accumated data. * * @return the value of the count field, which is the number * of valid bytes in this output stream. * @see #count * @throws java.io.IOException never */ public synchronized int size() throws IOException { return count; } /** * Sets the size of this stream"s accumulated data. <p> * * @param newSize the new size * @throws ArrayIndexOutOfBoundsException if new size is negative */ public synchronized void setSize(int newSize) { if (newSize < 0) { throw new ArrayIndexOutOfBoundsException(newSize); } else if (newSize > buf.length) { buf = copyOf(buf, Math.max(buf.length << 1, newSize)); } count = newSize; } /** * Performs an effecient (zero-copy) conversion of the data accumulated in * this output stream to an input stream. <p> * * To ensure the future integrity of the resulting input stream, {@link * #free() free} is invoked upon this output stream as a side-effect. * * @return an input stream representing this output stream"s accumulated * data * @throws java.io.IOException if an I/O error occurs. * In particular, an IOException may be thrown * if this output stream has been {@link #free() freed}. */ public synchronized ByteArrayInputStream toByteArrayInputStream() throws IOException { checkFreed(); ByteArrayInputStream inputStream = new ByteArrayInputStream(buf, 0, count); free(); return inputStream; } /** * Converts this stream"s accumuated data into a string, translating bytes * into characters according to the platform"s default character encoding. * * @return String translated from this stream"s accumuated data. * @throws RuntimeException may be thrown if this output stream has been * {@link #free() freed}. */ public synchronized String toString() { try { checkFreed(); } catch (IOException ex) { throw new RuntimeException(ex.toString()); } return new String(buf, 0, count); } /** * Converts this stream"s accumuated data into a string, translating bytes * into characters according to the specified character encoding. * * @return String translated from the buffer"s contents. * @param enc a character-encoding name. * @throws java.io.IOException may be thrown if this output stream has been * {@link #free() freed}. * @throws UnsupportedEncodingException If the named encoding is not * supported. */ public synchronized String toString(String enc) throws IOException, UnsupportedEncodingException { checkFreed(); return new String(buf, 0, count, enc); } /** * Closes this object for further writing. <p> * * Other operations may continue to succeed until after the first invocation * of {@link #free() free()}. <p> * * @throws java.io.IOException if an I/O error occurs (default: never) */ public synchronized void close() throws IOException { closed = true; } /** * Retrieves whether this stream is closed. <p> * @return true if this stream is closed, else false */ public synchronized boolean isClosed() { return closed; } /** * Closes this object and releases the underlying buffer for * garbage collection. <p> * * @throws java.io.IOException if an I/O error occurs while closing * this stream (default: never). */ public synchronized void free() throws IOException { closed = true; freed = true; buf = null; count = 0; } /** * Retrieves whether this stream is freed. <p> * * @return true if this stream is freed; else false. */ public synchronized boolean isFreed() { return freed; } /** * Tests whether this stream is closed. <p> * * @throws java.io.IOException if this stream is closed. */ protected synchronized void checkClosed() throws IOException { if (closed) { throw new IOException("stream is closed."); // NOI18N } } /** * Tests whether this stream is freed. <p> * * @throws java.io.IOException if this stream is freed. */ protected synchronized void checkFreed() throws IOException { if (freed) { throw new IOException("stream buffer is freed."); // NOI18N } } /** * Retrieves a copy of original with the given * newLength. <p> * * @param original the object to copy * @param newLength the length of the copy * @return copy of original with the given newLength */ protected byte[] copyOf(byte[] original, int newLength) { byte[] copy = new byte[newLength]; System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength)); return copy; }
}
</source>
Use ByteArrayOutputStream
<source lang="java">
import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; public class ByteArrayIOApp {
public static void main(String args[]) throws IOException { ByteArrayOutputStream outStream = new ByteArrayOutputStream(); String s = "This is a test."; for (int i = 0; i < s.length(); ++i) outStream.write(s.charAt(i)); System.out.println("outstream: " + outStream); System.out.println("size: " + outStream.size()); ByteArrayInputStream inStream; inStream = new ByteArrayInputStream(outStream.toByteArray()); int inBytes = inStream.available(); System.out.println("inStream has " + inBytes + " available bytes"); byte inBuf[] = new byte[inBytes]; int bytesRead = inStream.read(inBuf, 0, inBytes); System.out.println(bytesRead + " bytes were read"); System.out.println("They are: " + new String(inBuf)); }
}
</source>