1e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru/* 2e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * Licensed to the Apache Software Foundation (ASF) under one or more 3e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * contributor license agreements. See the NOTICE file distributed with 4e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * this work for additional information regarding copyright ownership. 5e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * The ASF licenses this file to You under the Apache License, Version 2.0 6e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * (the "License"); you may not use this file except in compliance with 7e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * the License. You may obtain a copy of the License at 8e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * 9e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * http://www.apache.org/licenses/LICENSE-2.0 10e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * 11e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * Unless required by applicable law or agreed to in writing, software 12e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * distributed under the License is distributed on an "AS IS" BASIS, 13e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * See the License for the specific language governing permissions and 15e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * limitations under the License. 16e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru */ 17e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Querupackage org.apache.commons.io.output; 18e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru 19e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queruimport java.io.IOException; 20e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queruimport java.io.InputStream; 21e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queruimport java.io.OutputStream; 22e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queruimport java.io.UnsupportedEncodingException; 23e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queruimport java.util.ArrayList; 24e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queruimport java.util.List; 25e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru 26e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru/** 27e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * This class implements an output stream in which the data is 28e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * written into a byte array. The buffer automatically grows as data 29e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * is written to it. 30e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * <p> 31e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * The data can be retrieved using <code>toByteArray()</code> and 32e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * <code>toString()</code>. 33e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * <p> 34e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * Closing a <tt>ByteArrayOutputStream</tt> has no effect. The methods in 35e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * this class can be called after the stream has been closed without 36e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * generating an <tt>IOException</tt>. 37e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * <p> 38e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * This is an alternative implementation of the java.io.ByteArrayOutputStream 39e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * class. The original implementation only allocates 32 bytes at the beginning. 40e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * As this class is designed for heavy duty it starts at 1024 bytes. In contrast 41e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * to the original it doesn't reallocate the whole memory block but allocates 42e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * additional buffers. This way no buffers need to be garbage collected and 43e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * the contents don't have to be copied to the new buffer. This class is 44e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * designed to behave exactly like the original. The only exception is the 45e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * deprecated toString(int) method that has been ignored. 46e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * 47e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a> 48e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * @author Holger Hoffstatte 49e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * @version $Id: ByteArrayOutputStream.java 610010 2008-01-08 14:50:59Z niallp $ 50e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru */ 51e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Querupublic class ByteArrayOutputStream extends OutputStream { 52e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru 53e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru /** A singleton empty byte array. */ 54e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru private static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; 55e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru 56e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru /** The list of buffers, which grows and never reduces. */ 57e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru private List<byte[]> buffers = new ArrayList<byte[]>(); 58e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru /** The index of the current buffer. */ 59e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru private int currentBufferIndex; 60e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru /** The total count of bytes in all the filled buffers. */ 61e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru private int filledBufferSum; 62e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru /** The current buffer. */ 63e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru private byte[] currentBuffer; 64e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru /** The total count of bytes written. */ 65e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru private int count; 66e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru 67e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru /** 68e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * Creates a new byte array output stream. The buffer capacity is 69e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * initially 1024 bytes, though its size increases if necessary. 70e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru */ 71e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru public ByteArrayOutputStream() { 72e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru this(1024); 73e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru } 74e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru 75e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru /** 76e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * Creates a new byte array output stream, with a buffer capacity of 77e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * the specified size, in bytes. 78e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * 79e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * @param size the initial size 80e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * @throws IllegalArgumentException if size is negative 81e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru */ 82e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru public ByteArrayOutputStream(int size) { 83e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru if (size < 0) { 84e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru throw new IllegalArgumentException( 85e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru "Negative initial size: " + size); 86e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru } 87e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru needNewBuffer(size); 88e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru } 89e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru 90e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru /** 91e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * Return the appropriate <code>byte[]</code> buffer 92e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * specified by index. 93e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * 94e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * @param index the index of the buffer required 95e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * @return the buffer 96e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru */ 97e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru private byte[] getBuffer(int index) { 98e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru return buffers.get(index); 99e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru } 100e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru 101e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru /** 102e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * Makes a new buffer available either by allocating 103e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * a new one or re-cycling an existing one. 104e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * 105e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * @param newcount the size of the buffer if one is created 106e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru */ 107e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru private void needNewBuffer(int newcount) { 108e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru if (currentBufferIndex < buffers.size() - 1) { 109e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru //Recycling old buffer 110e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru filledBufferSum += currentBuffer.length; 111e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru 112e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru currentBufferIndex++; 113e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru currentBuffer = getBuffer(currentBufferIndex); 114e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru } else { 115e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru //Creating new buffer 116e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru int newBufferSize; 117e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru if (currentBuffer == null) { 118e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru newBufferSize = newcount; 119e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru filledBufferSum = 0; 120e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru } else { 121e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru newBufferSize = Math.max( 122e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru currentBuffer.length << 1, 123e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru newcount - filledBufferSum); 124e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru filledBufferSum += currentBuffer.length; 125e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru } 126e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru 127e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru currentBufferIndex++; 128e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru currentBuffer = new byte[newBufferSize]; 129e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru buffers.add(currentBuffer); 130e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru } 131e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru } 132e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru 133e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru /** 134e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * Write the bytes to byte array. 135e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * @param b the bytes to write 136e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * @param off The start offset 137e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * @param len The number of bytes to write 138e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru */ 139e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru @Override 140e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru public void write(byte[] b, int off, int len) { 141e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru if ((off < 0) 142e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru || (off > b.length) 143e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru || (len < 0) 144e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru || ((off + len) > b.length) 145e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru || ((off + len) < 0)) { 146e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru throw new IndexOutOfBoundsException(); 147e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru } else if (len == 0) { 148e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru return; 149e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru } 150e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru synchronized (this) { 151e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru int newcount = count + len; 152e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru int remaining = len; 153e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru int inBufferPos = count - filledBufferSum; 154e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru while (remaining > 0) { 155e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru int part = Math.min(remaining, currentBuffer.length - inBufferPos); 156e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru System.arraycopy(b, off + len - remaining, currentBuffer, inBufferPos, part); 157e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru remaining -= part; 158e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru if (remaining > 0) { 159e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru needNewBuffer(newcount); 160e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru inBufferPos = 0; 161e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru } 162e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru } 163e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru count = newcount; 164e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru } 165e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru } 166e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru 167e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru /** 168e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * Write a byte to byte array. 169e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * @param b the byte to write 170e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru */ 171e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru @Override 172e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru public synchronized void write(int b) { 173e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru int inBufferPos = count - filledBufferSum; 174e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru if (inBufferPos == currentBuffer.length) { 175e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru needNewBuffer(count + 1); 176e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru inBufferPos = 0; 177e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru } 178e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru currentBuffer[inBufferPos] = (byte) b; 179e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru count++; 180e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru } 181e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru 182e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru /** 183e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * Writes the entire contents of the specified input stream to this 184e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * byte stream. Bytes from the input stream are read directly into the 185e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * internal buffers of this streams. 186e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * 187e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * @param in the input stream to read from 188e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * @return total number of bytes read from the input stream 189e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * (and written to this stream) 190e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * @throws IOException if an I/O error occurs while reading the input stream 191e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * @since Commons IO 1.4 192e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru */ 193e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru public synchronized int write(InputStream in) throws IOException { 194e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru int readCount = 0; 195e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru int inBufferPos = count - filledBufferSum; 196e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru int n = in.read(currentBuffer, inBufferPos, currentBuffer.length - inBufferPos); 197e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru while (n != -1) { 198e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru readCount += n; 199e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru inBufferPos += n; 200e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru count += n; 201e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru if (inBufferPos == currentBuffer.length) { 202e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru needNewBuffer(currentBuffer.length); 203e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru inBufferPos = 0; 204e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru } 205e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru n = in.read(currentBuffer, inBufferPos, currentBuffer.length - inBufferPos); 206e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru } 207e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru return readCount; 208e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru } 209e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru 210e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru /** 211e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * Return the current size of the byte array. 212e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * @return the current size of the byte array 213e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru */ 214e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru public synchronized int size() { 215e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru return count; 216e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru } 217e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru 218e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru /** 219e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * Closing a <tt>ByteArrayOutputStream</tt> has no effect. The methods in 220e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * this class can be called after the stream has been closed without 221e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * generating an <tt>IOException</tt>. 222e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * 223e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * @throws IOException never (this method should not declare this exception 224e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * but it has to now due to backwards compatability) 225e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru */ 226e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru @Override 227e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru public void close() throws IOException { 228e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru //nop 229e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru } 230e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru 231e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru /** 232e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * @see java.io.ByteArrayOutputStream#reset() 233e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru */ 234e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru public synchronized void reset() { 235e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru count = 0; 236e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru filledBufferSum = 0; 237e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru currentBufferIndex = 0; 238e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru currentBuffer = getBuffer(currentBufferIndex); 239e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru } 240e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru 241e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru /** 242e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * Writes the entire contents of this byte stream to the 243e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * specified output stream. 244e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * 245e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * @param out the output stream to write to 246e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * @throws IOException if an I/O error occurs, such as if the stream is closed 247e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * @see java.io.ByteArrayOutputStream#writeTo(OutputStream) 248e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru */ 249e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru public synchronized void writeTo(OutputStream out) throws IOException { 250e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru int remaining = count; 251e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru for (int i = 0; i < buffers.size(); i++) { 252e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru byte[] buf = getBuffer(i); 253e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru int c = Math.min(buf.length, remaining); 254e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru out.write(buf, 0, c); 255e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru remaining -= c; 256e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru if (remaining == 0) { 257e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru break; 258e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru } 259e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru } 260e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru } 261e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru 262e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru /** 263e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * Gets the curent contents of this byte stream as a byte array. 264e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * The result is independent of this stream. 265e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * 266e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * @return the current contents of this output stream, as a byte array 267e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * @see java.io.ByteArrayOutputStream#toByteArray() 268e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru */ 269e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru public synchronized byte[] toByteArray() { 270e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru int remaining = count; 271e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru if (remaining == 0) { 272e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru return EMPTY_BYTE_ARRAY; 273e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru } 274e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru byte newbuf[] = new byte[remaining]; 275e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru int pos = 0; 276e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru for (int i = 0; i < buffers.size(); i++) { 277e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru byte[] buf = getBuffer(i); 278e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru int c = Math.min(buf.length, remaining); 279e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru System.arraycopy(buf, 0, newbuf, pos, c); 280e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru pos += c; 281e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru remaining -= c; 282e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru if (remaining == 0) { 283e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru break; 284e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru } 285e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru } 286e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru return newbuf; 287e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru } 288e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru 289e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru /** 290e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * Gets the curent contents of this byte stream as a string. 291e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * @return the contents of the byte array as a String 292e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * @see java.io.ByteArrayOutputStream#toString() 293e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru */ 294e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru @Override 295e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru public String toString() { 296e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru return new String(toByteArray()); 297e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru } 298e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru 299e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru /** 300e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * Gets the curent contents of this byte stream as a string 301e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * using the specified encoding. 302e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * 303e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * @param enc the name of the character encoding 304e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * @return the string converted from the byte array 305e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * @throws UnsupportedEncodingException if the encoding is not supported 306e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru * @see java.io.ByteArrayOutputStream#toString(String) 307e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru */ 308e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru public String toString(String enc) throws UnsupportedEncodingException { 309e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru return new String(toByteArray(), enc); 310e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru } 311e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru 312e858128e970bdead5d5a096d9b5d941b2f5efadeJean-Baptiste Queru} 313