001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package java.io;
019:
020: import org.apache.harmony.luni.util.Msg;
021:
022: /**
023: * ByteArrayOutputStream is a class whose underlying stream is represented by a
024: * byte array. As bytes are written to this stream, the local byte array may be
025: * expanded to hold more bytes.
026: *
027: * @see ByteArrayInputStream
028: */
029: public class ByteArrayOutputStream extends OutputStream {
030: /**
031: * The byte array containing the bytes written.
032: */
033: protected byte[] buf;
034:
035: /**
036: * The number of bytes written.
037: */
038: protected int count;
039:
040: /**
041: * Constructs a new ByteArrayOutputStream with a default size of 32 bytes.
042: * If more than 32 bytes are written to this instance, the underlying byte
043: * array will expand to accommodate.
044: *
045: */
046: public ByteArrayOutputStream() {
047: super ();
048: buf = new byte[32];
049: }
050:
051: /**
052: * Constructs a new ByteArrayOutputStream with a default size of
053: * <code>size</code> bytes. If more than <code>size</code> bytes are
054: * written to this instance, the underlying byte array will expand to
055: * accommodate.
056: *
057: * @param size
058: * an non-negative integer representing the initial size for the
059: * underlying byte array.
060: */
061: public ByteArrayOutputStream(int size) {
062: super ();
063: if (size >= 0) {
064: buf = new byte[size];
065: } else {
066: throw new IllegalArgumentException(Msg.getString("K005e")); //$NON-NLS-1$
067: }
068: }
069:
070: /**
071: * Close this ByteArrayOutputStream. This implementation releases System
072: * resources used for this stream.
073: *
074: * @throws IOException
075: * If an error occurs attempting to close this OutputStream.
076: */
077: @Override
078: public void close() throws IOException {
079: /**
080: * Although the spec claims "A closed stream cannot perform output
081: * operations and cannot be reopened.", this implementation must do
082: * nothing.
083: */
084: super .close();
085: }
086:
087: private void expand(int i) {
088: /* Can the buffer handle @i more bytes, if not expand it */
089: if (count + i <= buf.length) {
090: return;
091: }
092:
093: byte[] newbuf = new byte[(count + i) * 2];
094: System.arraycopy(buf, 0, newbuf, 0, count);
095: buf = newbuf;
096: }
097:
098: /**
099: * Reset this ByteArrayOutputStream to the beginning of the underlying byte
100: * array. All subsequent writes will overwrite any bytes previously stored
101: * in this stream.
102: *
103: */
104: public synchronized void reset() {
105: count = 0;
106: }
107:
108: /**
109: * Answers the total number of bytes written to this stream thus far.
110: *
111: * @return the number of bytes written to this Stream.
112: */
113: public int size() {
114: return count;
115: }
116:
117: /**
118: * Answer the contents of this ByteArrayOutputStream as a byte array. Any
119: * changes made to the receiver after returning will not be reflected in the
120: * byte array returned to the caller.
121: *
122: * @return this streams current contents as a byte array.
123: */
124: public synchronized byte[] toByteArray() {
125: byte[] newArray = new byte[count];
126: System.arraycopy(buf, 0, newArray, 0, count);
127: return newArray;
128: }
129:
130: /**
131: * Answer the contents of this ByteArrayOutputStream as a String. Any
132: * changes made to the receiver after returning will not be reflected in the
133: * String returned to the caller.
134: *
135: * @return this streams current contents as a String.
136: */
137:
138: @Override
139: public String toString() {
140: return new String(buf, 0, count);
141: }
142:
143: /**
144: * Answer the contents of this ByteArrayOutputStream as a String. Each byte
145: * <code>b</code> in this stream is converted to a character
146: * <code>c</code> using the following function:
147: * <code>c == (char)(((hibyte & 0xff) << 8) | (b & 0xff))</code>. This
148: * method is deprecated and either toString(), or toString(enc) should be
149: * used.
150: *
151: * @param hibyte
152: * the high byte of each resulting Unicode character
153: * @return this streams current contents as a String with the high byte set
154: * to <code>hibyte</code>
155: *
156: * @deprecated Use toString()
157: */
158: @Deprecated
159: public String toString(int hibyte) {
160: char[] newBuf = new char[size()];
161: for (int i = 0; i < newBuf.length; i++) {
162: newBuf[i] = (char) (((hibyte & 0xff) << 8) | (buf[i] & 0xff));
163: }
164: return new String(newBuf);
165: }
166:
167: /**
168: * Answer the contents of this ByteArrayOutputStream as a String converted
169: * using the encoding declared in <code>enc</code>.
170: *
171: * @param enc
172: * A String representing the encoding to use when translating
173: * this stream to a String.
174: * @return this streams current contents as a String.
175: *
176: * @throws UnsupportedEncodingException
177: * If declared encoding is not supported
178: */
179: public String toString(String enc)
180: throws UnsupportedEncodingException {
181: return new String(buf, 0, count, enc);
182: }
183:
184: /**
185: * Writes <code>count</code> <code>bytes</code> from the byte array
186: * <code>buffer</code> starting at offset <code>index</code> to the
187: * ByteArrayOutputStream.
188: *
189: * @param buffer
190: * the buffer to be written
191: * @param offset
192: * offset in buffer to get bytes
193: * @param len
194: * number of bytes in buffer to write
195: *
196: * @throws NullPointerException
197: * If buffer is null.
198: * @throws IndexOutOfBoundsException
199: * If offset or count are outside of bounds.
200: */
201: @Override
202: public synchronized void write(byte[] buffer, int offset, int len) {
203: // avoid int overflow
204: if (offset < 0 || offset > buffer.length || len < 0
205: || len > buffer.length - offset) {
206: throw new IndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
207: }
208: if (len == 0) {
209: return;
210: }
211:
212: /* Expand if necessary */
213: expand(len);
214: System.arraycopy(buffer, offset, buf, this .count, len);
215: this .count += len;
216: }
217:
218: /**
219: * Writes the specified byte <code>oneByte</code> to the OutputStream.
220: * Only the low order byte of <code>oneByte</code> is written.
221: *
222: * @param oneByte
223: * the byte to be written
224: */
225: @Override
226: public synchronized void write(int oneByte) {
227: if (count == buf.length) {
228: expand(1);
229: }
230: buf[count++] = (byte) oneByte;
231: }
232:
233: /**
234: * Take the contents of this stream and write it to the output stream
235: * <code>out</code>.
236: *
237: * @param out
238: * An OutputStream on which to write the contents of this stream.
239: *
240: * @throws IOException
241: * If an error occurs when writing to output stream
242: */
243: public synchronized void writeTo(OutputStream out)
244: throws IOException {
245: out.write(buf, 0, count);
246: }
247: }
|