14fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy/* 24fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Licensed to the Apache Software Foundation (ASF) under one or more 34fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * contributor license agreements. See the NOTICE file distributed with 44fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * this work for additional information regarding copyright ownership. 54fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The ASF licenses this file to You under the Apache License, Version 2.0 64fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * (the "License"); you may not use this file except in compliance with 74fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * the License. You may obtain a copy of the License at 84fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 94fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * http://www.apache.org/licenses/LICENSE-2.0 104fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 114fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Unless required by applicable law or agreed to in writing, software 124fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * distributed under the License is distributed on an "AS IS" BASIS, 134fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 144fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * See the License for the specific language governing permissions and 154fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * limitations under the License. 164fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 174fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedypackage org.apache.commons.io.output; 184fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 194fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedyimport java.io.IOException; 204fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedyimport java.io.InputStream; 214fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedyimport java.io.OutputStream; 224fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedyimport java.io.UnsupportedEncodingException; 234fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedyimport java.util.ArrayList; 244fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedyimport java.util.List; 254fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 264fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy/** 274fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * This class implements an output stream in which the data is 284fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * written into a byte array. The buffer automatically grows as data 294fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * is written to it. 304fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 314fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The data can be retrieved using <code>toByteArray()</code> and 324fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <code>toString()</code>. 334fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 344fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Closing a <tt>ByteArrayOutputStream</tt> has no effect. The methods in 354fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * this class can be called after the stream has been closed without 364fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * generating an <tt>IOException</tt>. 374fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p> 384fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * This is an alternative implementation of the java.io.ByteArrayOutputStream 394fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * class. The original implementation only allocates 32 bytes at the beginning. 404fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * As this class is designed for heavy duty it starts at 1024 bytes. In contrast 414fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * to the original it doesn't reallocate the whole memory block but allocates 424fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * additional buffers. This way no buffers need to be garbage collected and 434fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * the contents don't have to be copied to the new buffer. This class is 444fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * designed to behave exactly like the original. The only exception is the 454fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * deprecated toString(int) method that has been ignored. 464fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 474fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a> 484fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @author Holger Hoffstatte 494fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @version $Id: ByteArrayOutputStream.java 610010 2008-01-08 14:50:59Z niallp $ 504fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 514fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedypublic class ByteArrayOutputStream extends OutputStream { 524fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 534fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** A singleton empty byte array. */ 544fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy private static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; 554fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 564fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** The list of buffers, which grows and never reduces. */ 574fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy private List<byte[]> buffers = new ArrayList<byte[]>(); 584fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** The index of the current buffer. */ 594fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy private int currentBufferIndex; 604fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** The total count of bytes in all the filled buffers. */ 614fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy private int filledBufferSum; 624fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** The current buffer. */ 634fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy private byte[] currentBuffer; 644fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** The total count of bytes written. */ 654fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy private int count; 664fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 674fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 684fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Creates a new byte array output stream. The buffer capacity is 694fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * initially 1024 bytes, though its size increases if necessary. 704fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 714fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public ByteArrayOutputStream() { 724fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy this(1024); 734fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 744fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 754fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 764fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Creates a new byte array output stream, with a buffer capacity of 774fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * the specified size, in bytes. 784fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 794fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param size the initial size 804fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @throws IllegalArgumentException if size is negative 814fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 824fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public ByteArrayOutputStream(int size) { 834fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (size < 0) { 844fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy throw new IllegalArgumentException( 854fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy "Negative initial size: " + size); 864fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 874fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy needNewBuffer(size); 884fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 894fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 904fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 914fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Return the appropriate <code>byte[]</code> buffer 924fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * specified by index. 934fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 944fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param index the index of the buffer required 954fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return the buffer 964fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 974fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy private byte[] getBuffer(int index) { 984fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return buffers.get(index); 994fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 1004fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 1014fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 1024fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Makes a new buffer available either by allocating 1034fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * a new one or re-cycling an existing one. 1044fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 1054fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param newcount the size of the buffer if one is created 1064fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 1074fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy private void needNewBuffer(int newcount) { 1084fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (currentBufferIndex < buffers.size() - 1) { 1094fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy //Recycling old buffer 1104fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy filledBufferSum += currentBuffer.length; 1114fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 1124fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy currentBufferIndex++; 1134fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy currentBuffer = getBuffer(currentBufferIndex); 1144fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } else { 1154fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy //Creating new buffer 1164fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int newBufferSize; 1174fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (currentBuffer == null) { 1184fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy newBufferSize = newcount; 1194fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy filledBufferSum = 0; 1204fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } else { 1214fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy newBufferSize = Math.max( 1224fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy currentBuffer.length << 1, 1234fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy newcount - filledBufferSum); 1244fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy filledBufferSum += currentBuffer.length; 1254fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 1264fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 1274fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy currentBufferIndex++; 1284fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy currentBuffer = new byte[newBufferSize]; 1294fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy buffers.add(currentBuffer); 1304fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 1314fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 1324fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 1334fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 1344fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Write the bytes to byte array. 1354fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param b the bytes to write 1364fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param off The start offset 1374fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param len The number of bytes to write 1384fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 1394fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy @Override 1404fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public void write(byte[] b, int off, int len) { 1414fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if ((off < 0) 1424fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy || (off > b.length) 1434fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy || (len < 0) 1444fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy || ((off + len) > b.length) 1454fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy || ((off + len) < 0)) { 1464fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy throw new IndexOutOfBoundsException(); 1474fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } else if (len == 0) { 1484fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return; 1494fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 1504fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy synchronized (this) { 1514fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int newcount = count + len; 1524fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int remaining = len; 1534fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int inBufferPos = count - filledBufferSum; 1544fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy while (remaining > 0) { 1554fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int part = Math.min(remaining, currentBuffer.length - inBufferPos); 1564fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy System.arraycopy(b, off + len - remaining, currentBuffer, inBufferPos, part); 1574fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy remaining -= part; 1584fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (remaining > 0) { 1594fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy needNewBuffer(newcount); 1604fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy inBufferPos = 0; 1614fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 1624fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 1634fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy count = newcount; 1644fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 1654fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 1664fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 1674fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 1684fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Write a byte to byte array. 1694fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param b the byte to write 1704fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 1714fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy @Override 1724fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public synchronized void write(int b) { 1734fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int inBufferPos = count - filledBufferSum; 1744fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (inBufferPos == currentBuffer.length) { 1754fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy needNewBuffer(count + 1); 1764fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy inBufferPos = 0; 1774fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 1784fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy currentBuffer[inBufferPos] = (byte) b; 1794fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy count++; 1804fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 1814fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 1824fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 1834fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Writes the entire contents of the specified input stream to this 1844fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * byte stream. Bytes from the input stream are read directly into the 1854fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * internal buffers of this streams. 1864fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 1874fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param in the input stream to read from 1884fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return total number of bytes read from the input stream 1894fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * (and written to this stream) 1904fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @throws IOException if an I/O error occurs while reading the input stream 1914fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @since Commons IO 1.4 1924fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 1934fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public synchronized int write(InputStream in) throws IOException { 1944fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int readCount = 0; 1954fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int inBufferPos = count - filledBufferSum; 1964fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int n = in.read(currentBuffer, inBufferPos, currentBuffer.length - inBufferPos); 1974fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy while (n != -1) { 1984fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy readCount += n; 1994fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy inBufferPos += n; 2004fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy count += n; 2014fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (inBufferPos == currentBuffer.length) { 2024fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy needNewBuffer(currentBuffer.length); 2034fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy inBufferPos = 0; 2044fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2054fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy n = in.read(currentBuffer, inBufferPos, currentBuffer.length - inBufferPos); 2064fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2074fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return readCount; 2084fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2094fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 2104fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 2114fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Return the current size of the byte array. 2124fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return the current size of the byte array 2134fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 2144fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public synchronized int size() { 2154fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return count; 2164fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2174fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 2184fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 2194fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Closing a <tt>ByteArrayOutputStream</tt> has no effect. The methods in 2204fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * this class can be called after the stream has been closed without 2214fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * generating an <tt>IOException</tt>. 2224fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 2234fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @throws IOException never (this method should not declare this exception 2244fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * but it has to now due to backwards compatability) 2254fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 2264fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy @Override 2274fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public void close() throws IOException { 2284fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy //nop 2294fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2304fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 2314fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 2324fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @see java.io.ByteArrayOutputStream#reset() 2334fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 2344fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public synchronized void reset() { 2354fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy count = 0; 2364fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy filledBufferSum = 0; 2374fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy currentBufferIndex = 0; 2384fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy currentBuffer = getBuffer(currentBufferIndex); 2394fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2404fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 2414fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 2424fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Writes the entire contents of this byte stream to the 2434fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * specified output stream. 2444fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 2454fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param out the output stream to write to 2464fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @throws IOException if an I/O error occurs, such as if the stream is closed 2474fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @see java.io.ByteArrayOutputStream#writeTo(OutputStream) 2484fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 2494fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public synchronized void writeTo(OutputStream out) throws IOException { 2504fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int remaining = count; 2514fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy for (int i = 0; i < buffers.size(); i++) { 2524fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy byte[] buf = getBuffer(i); 2534fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int c = Math.min(buf.length, remaining); 2544fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy out.write(buf, 0, c); 2554fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy remaining -= c; 2564fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (remaining == 0) { 2574fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy break; 2584fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2594fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2604fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2614fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 2624fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 2634fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Gets the curent contents of this byte stream as a byte array. 2644fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The result is independent of this stream. 2654fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 2664fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return the current contents of this output stream, as a byte array 2674fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @see java.io.ByteArrayOutputStream#toByteArray() 2684fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 2694fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public synchronized byte[] toByteArray() { 2704fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int remaining = count; 2714fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (remaining == 0) { 2724fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return EMPTY_BYTE_ARRAY; 2734fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2744fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy byte newbuf[] = new byte[remaining]; 2754fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int pos = 0; 2764fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy for (int i = 0; i < buffers.size(); i++) { 2774fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy byte[] buf = getBuffer(i); 2784fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy int c = Math.min(buf.length, remaining); 2794fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy System.arraycopy(buf, 0, newbuf, pos, c); 2804fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy pos += c; 2814fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy remaining -= c; 2824fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy if (remaining == 0) { 2834fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy break; 2844fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2854fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2864fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return newbuf; 2874fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2884fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 2894fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 2904fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Gets the curent contents of this byte stream as a string. 2914fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return the contents of the byte array as a String 2924fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @see java.io.ByteArrayOutputStream#toString() 2934fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 2944fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy @Override 2954fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public String toString() { 2964fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return new String(toByteArray()); 2974fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 2984fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 2994fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy /** 3004fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Gets the curent contents of this byte stream as a string 3014fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * using the specified encoding. 3024fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * 3034fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @param enc the name of the character encoding 3044fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @return the string converted from the byte array 3054fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @throws UnsupportedEncodingException if the encoding is not supported 3064fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @see java.io.ByteArrayOutputStream#toString(String) 3074fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */ 3084fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy public String toString(String enc) throws UnsupportedEncodingException { 3094fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy return new String(toByteArray(), enc); 3104fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy } 3114fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy 3124fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy} 313