/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//Revised from Apache cocoon
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* This class is like the {@link java.io.BufferedOutputStream} but it
* extends it with a logic to count the number of bytes written to
* the output stream.
*
* @version $Id: BufferedOutputStream.java 587751 2007-10-24 02:41:36Z vgritsenko $
* @since 2.1
*/
public final class BufferedOutputStream extends FilterOutputStream {
protected byte buf[];
protected int count;
/**
* Creates a new buffered output stream to write data to the
* specified underlying output stream with a default 8192-byte
* buffer size.
*
* @param out the underlying output stream.
*/
public BufferedOutputStream(OutputStream out) {
this(out, 8192);
}
/**
* Creates a new buffered output stream to write data to the
* specified underlying output stream with the specified buffer
* size.
*
* @param out the underlying output stream.
* @param size the buffer size.
* @exception IllegalArgumentException if size <= 0.
*/
public BufferedOutputStream(OutputStream out, int size) {
super(out);
if (size <= 0) {
throw new IllegalArgumentException("Buffer size <= 0");
}
this.buf = new byte[size];
}
/**
* Writes the specified byte to this buffered output stream.
*
* @param b the byte to be written.
* @exception IOException if an I/O error occurs.
*/
public void write(int b) throws IOException {
if (this.count >= this.buf.length) {
this.incBuffer();
}
this.buf[count++] = (byte)b;
}
/**
* Writes <code>len</code> bytes from the specified byte array
* starting at offset <code>off</code> to this buffered output stream.
*
* Ordinarily this method stores bytes from the given array into this
* stream's buffer, flushing the buffer to the underlying output stream as
* needed. If the requested length is at least as large as this stream's
* buffer, however, then this method will flush the buffer and write the
* bytes directly to the underlying output stream. Thus redundant
* <code>BufferedOutputStream</code>s will not copy data unnecessarily.
*
* @param b the data.
* @param off the start offset in the data.
* @param len the number of bytes to write.
* @exception IOException if an I/O error occurs.
*/
public void write(byte b[], int off, int len) throws IOException {
while (len > buf.length - count) {
this.incBuffer();
}
System.arraycopy(b, off, buf, count, len);
count += len;
}
/**
* Flushes this buffered output stream.
* We don't flush here, flushing is done during closing.
*
* @exception IOException if an I/O error occurs.
*/
public void flush() throws IOException {
// nothing
}
/**
* Closes this buffered output stream.
* Flush before closing.
*
* @exception IOException if an I/O error occurs.
*/
public void close() throws IOException {
realFlush();
super.close ();
}
/**
* Flushes this buffered output stream.
*/
public void realFlush() throws IOException {
this.writeBuffer();
this.out.flush();
}
/**
* Write the buffer
*/
private void writeBuffer()
throws IOException {
if (this.count > 0) {
this.out.write(this.buf, 0, this.count);
this.clearBuffer();
}
}
/**
* Increment the buffer
*/
private void incBuffer() {
// currently we double the buffer size
// this is not so fast but is a very simple logic
byte[] newBuf = new byte[this.buf.length * 2];
System.arraycopy(this.buf, 0, newBuf, 0, this.buf.length);
this.buf = newBuf;
}
/**
* Clear/reset the buffer
*/
public void clearBuffer() {
this.count = 0;
}
/**
* Return the size of the current buffer
*/
public int getCount() {
return this.count;
}
}