1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* 2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Licensed to the Apache Software Foundation (ASF) under one or more 3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * contributor license agreements. See the NOTICE file distributed with 4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this work for additional information regarding copyright ownership. 5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The ASF licenses this file to You under the Apache License, Version 2.0 6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (the "License"); you may not use this file except in compliance with 7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the License. You may obtain a copy of the License at 8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and 15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License. 16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage java.io; 19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 20b9cc455ed89df1a0cf4186c92b352c9649995d96Elliott Hughesimport java.util.Arrays; 21b9cc455ed89df1a0cf4186c92b352c9649995d96Elliott Hughes 22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Wraps an existing {@link OutputStream} and <em>buffers</em> the output. 24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Expensive interaction with the underlying input stream is minimized, since 25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * most (smaller) requests can be satisfied by accessing the buffer alone. The 26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * drawback is that some extra space is required to hold the buffer and that 27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * copying takes place when flushing that buffer, but this is usually outweighed 28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * by the performance benefits. 29f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p/>A typical application pattern for the class looks like this:<p/> 31f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <pre> 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * BufferedOutputStream buf = new BufferedOutputStream(new FileOutputStream("file.java")); 34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * </pre> 35f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see BufferedInputStream 37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic class BufferedOutputStream extends FilterOutputStream { 39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The buffer containing the bytes to be written to the target stream. 41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected byte[] buf; 43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The total number of bytes inside the byte array {@code buf}. 46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected int count; 48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 50fb4616d0efbba1903b9237c0a428b59868365a69Elliott Hughes * Constructs a new {@code BufferedOutputStream}, providing {@code out} with a buffer 51fb4616d0efbba1903b9237c0a428b59868365a69Elliott Hughes * of 8192 bytes. 52f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 53fb4616d0efbba1903b9237c0a428b59868365a69Elliott Hughes * @param out the {@code OutputStream} the buffer writes to. 54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public BufferedOutputStream(OutputStream out) { 56fb4616d0efbba1903b9237c0a428b59868365a69Elliott Hughes this(out, 8192); 57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 60fb4616d0efbba1903b9237c0a428b59868365a69Elliott Hughes * Constructs a new {@code BufferedOutputStream}, providing {@code out} with {@code size} bytes 61fb4616d0efbba1903b9237c0a428b59868365a69Elliott Hughes * of buffer. 62f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 63fb4616d0efbba1903b9237c0a428b59868365a69Elliott Hughes * @param out the {@code OutputStream} the buffer writes to. 64fb4616d0efbba1903b9237c0a428b59868365a69Elliott Hughes * @param size the size of buffer in bytes. 65fb4616d0efbba1903b9237c0a428b59868365a69Elliott Hughes * @throws IllegalArgumentException if {@code size <= 0}. 66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public BufferedOutputStream(OutputStream out, int size) { 68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(out); 69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (size <= 0) { 70b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new IllegalArgumentException("size <= 0"); 71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project buf = new byte[size]; 73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Flushes this stream to ensure all pending data is written out to the 77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * target stream. In addition, the target stream is flushed. 78f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if an error occurs attempting to flush this stream. 81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public synchronized void flush() throws IOException { 84b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes checkNotClosed(); 85f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson flushInternal(); 86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project out.flush(); 87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 89b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes private void checkNotClosed() throws IOException { 90b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes if (buf == null) { 91b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new IOException("BufferedOutputStream is closed"); 92b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes } 93b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes } 94b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes 95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Writes {@code count} bytes from the byte array {@code buffer} starting at 97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code offset} to this stream. If there is room in the buffer to hold the 98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * bytes, they are copied in. If not, the buffered bytes plus the bytes in 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code buffer} are written to the target stream, the target is flushed, 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * and the buffer is cleared. 101f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param buffer 103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the buffer to be written. 104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param offset 105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the start position in {@code buffer} from where to get bytes. 106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param length 107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the number of bytes from {@code buffer} to write to this 108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * stream. 109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IndexOutOfBoundsException 110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if {@code offset < 0} or {@code length < 0}, or if 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code offset + length} is greater than the size of 112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code buffer}. 113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if an error occurs attempting to write to this stream. 115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws NullPointerException 116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if {@code buffer} is {@code null}. 117f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * @throws ArrayIndexOutOfBoundsException 118f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * If offset or count is outside of bounds. 119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 121b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes public synchronized void write(byte[] buffer, int offset, int length) throws IOException { 122b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes checkNotClosed(); 12355392539fea537abfb6581b474918f9d611fba27Jesse Wilson 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (buffer == null) { 125b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new NullPointerException("buffer == null"); 126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 127f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 128b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes byte[] internalBuffer = buf; 12955392539fea537abfb6581b474918f9d611fba27Jesse Wilson if (length >= internalBuffer.length) { 130f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson flushInternal(); 131f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson out.write(buffer, offset, length); 132f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson return; 133f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 134f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 135b9cc455ed89df1a0cf4186c92b352c9649995d96Elliott Hughes Arrays.checkOffsetAndCount(buffer.length, offset, length); 136f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 137f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson // flush the internal buffer first if we have not enough space left 1380efebd8c734d30ed798b80166290b904fa357ee0Jesse Wilson if (length > (internalBuffer.length - count)) { 139f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson flushInternal(); 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 141f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 14255392539fea537abfb6581b474918f9d611fba27Jesse Wilson System.arraycopy(buffer, offset, internalBuffer, count, length); 143f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson count += length; 144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 14655392539fea537abfb6581b474918f9d611fba27Jesse Wilson @Override public synchronized void close() throws IOException { 14755392539fea537abfb6581b474918f9d611fba27Jesse Wilson if (buf == null) { 14855392539fea537abfb6581b474918f9d611fba27Jesse Wilson return; 14955392539fea537abfb6581b474918f9d611fba27Jesse Wilson } 150f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 15155392539fea537abfb6581b474918f9d611fba27Jesse Wilson try { 15255392539fea537abfb6581b474918f9d611fba27Jesse Wilson super.close(); 15355392539fea537abfb6581b474918f9d611fba27Jesse Wilson } finally { 15455392539fea537abfb6581b474918f9d611fba27Jesse Wilson buf = null; 15555392539fea537abfb6581b474918f9d611fba27Jesse Wilson } 15655392539fea537abfb6581b474918f9d611fba27Jesse Wilson } 15755392539fea537abfb6581b474918f9d611fba27Jesse Wilson 158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Writes one byte to this stream. Only the low order byte of the integer 160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code oneByte} is written. If there is room in the buffer, the byte is 161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * copied into the buffer and the count incremented. Otherwise, the buffer 162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * plus {@code oneByte} are written to the target stream, the target is 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * flushed, and the buffer is reset. 164f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param oneByte 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the byte to be written. 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if an error occurs attempting to write to this stream. 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public synchronized void write(int oneByte) throws IOException { 172b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes checkNotClosed(); 173b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes if (count == buf.length) { 174b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes out.write(buf, 0, count); 175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project count = 0; 176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 177b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes buf[count++] = (byte) oneByte; 178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 179f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 180f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson /** 181f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * Flushes only internal buffer. 182f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson */ 183f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson private void flushInternal() throws IOException { 184f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson if (count > 0) { 185f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson out.write(buf, 0, count); 18655392539fea537abfb6581b474918f9d611fba27Jesse Wilson count = 0; 187f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 188f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 190