I am refactoring some code and want to make a PrintWriter that will send output to two seperate Writer's (not streams, and they ultimately go different places, one of them may have other stuff sent to it from elsewhere).
For streams there is the Apache TeeOutputStream, is there anything for Writer or will I need to go via a stream and back to text?
There is no such "multiwriter" in the standard Java library, but you can create one very easily. The reason for "easily" is because there are only 3 abstract
methods in java.io.Writer
: close()
, flush()
and write(char[] cbuf, int off, int len)
.
The default implementation of all other overloads of the write()
method call this abstract one.
You just have to store the writers you want to forward to and do just that: forward the calls of these 3 abstract methods:
class MultiWriter extends Writer {
private final Writer[] writers;
public MultiWriter(Writer... writers) {
this.writers = writers;
}
@Override
public void write(char[] cbuf, int off, int len) throws IOException {
for (Writer w : writers)
w.write(cbuf, off, len);
}
@Override
public void flush() throws IOException {
for (Writer w : writers)
w.flush();
}
@Override
public void close() throws IOException {
for (Writer w : writers)
w.close();
}
};
Note:
I know you wanted a PrintWriter
, but since our MultiWriter
is a java.io.Writer
, you can simply pass it to a PrintWriter
like this:
PrintWriter pw = new PrintWriter(new MultiWriter(writer1, writer2));
Note #2:
In my implementation I did not catch exceptions thrown by the writers we forward to. If for example the write()
method of a "child" writer would thow an IOException
, even if we would succeed to write to other writers, the one that failed will still be failed... If we wanted to handle individual exceptions, we would have to implement a new IOException
that could hold a collection of other IOException
because multiple "child" writers could fail just as easily.