/* * 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. */ package org.apache.commons.io.input; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; /** * InputStream proxy that transparently writes a copy of all bytes read * from the proxied stream to a given OutputStream. Using {@link #skip(long)} * or {@link #mark(int)}/{@link #reset()} on the stream will result on some * bytes from the input stream being skipped or duplicated in the output * stream. *
* The proxied input stream is closed when the {@link #close()} method is
* called on this proxy. It is configurable whether the associated output
* stream will also closed.
*
* @version $Id: TeeInputStream.java 587913 2007-10-24 15:47:30Z niallp $
* @since Commons IO 1.4
*/
public class TeeInputStream extends ProxyInputStream {
/**
* The output stream that will receive a copy of all bytes read from the
* proxied input stream.
*/
private final OutputStream branch;
/**
* Flag for closing also the associated output stream when this
* stream is closed.
*/
private final boolean closeBranch;
/**
* Creates a TeeInputStream that proxies the given {@link InputStream}
* and copies all read bytes to the given {@link OutputStream}. The given
* output stream will not be closed when this stream gets closed.
*
* @param input input stream to be proxied
* @param branch output stream that will receive a copy of all bytes read
*/
public TeeInputStream(InputStream input, OutputStream branch) {
this(input, branch, false);
}
/**
* Creates a TeeInputStream that proxies the given {@link InputStream}
* and copies all read bytes to the given {@link OutputStream}. The given
* output stream will be closed when this stream gets closed if the
* closeBranch parameter is true
.
*
* @param input input stream to be proxied
* @param branch output stream that will receive a copy of all bytes read
* @param closeBranch flag for closing also the output stream when this
* stream is closed
*/
public TeeInputStream(
InputStream input, OutputStream branch, boolean closeBranch) {
super(input);
this.branch = branch;
this.closeBranch = closeBranch;
}
/**
* Closes the proxied input stream and, if so configured, the associated
* output stream. An exception thrown from one stream will not prevent
* closing of the other stream.
*
* @throws IOException if either of the streams could not be closed
*/
public void close() throws IOException {
try {
super.close();
} finally {
if (closeBranch) {
branch.close();
}
}
}
/**
* Reads a single byte from the proxied input stream and writes it to
* the associated output stream.
*
* @return next byte from the stream, or -1 if the stream has ended
* @throws IOException if the stream could not be read (or written)
*/
public int read() throws IOException {
int ch = super.read();
if (ch != -1) {
branch.write(ch);
}
return ch;
}
/**
* Reads bytes from the proxied input stream and writes the read bytes
* to the associated output stream.
*
* @param bts byte buffer
* @param st start offset within the buffer
* @param end maximum number of bytes to read
* @return number of bytes read, or -1 if the stream has ended
* @throws IOException if the stream could not be read (or written)
*/
public int read(byte[] bts, int st, int end) throws IOException {
int n = super.read(bts, st, end);
if (n != -1) {
branch.write(bts, st, n);
}
return n;
}
/**
* Reads bytes from the proxied input stream and writes the read bytes
* to the associated output stream.
*
* @param bts byte buffer
* @return number of bytes read, or -1 if the stream has ended
* @throws IOException if the stream could not be read (or written)
*/
public int read(byte[] bts) throws IOException {
int n = super.read(bts);
if (n != -1) {
branch.write(bts, 0, n);
}
return n;
}
}