tags:

views:

877

answers:

3

Is there a more concise/standard idiom (e.g., a JDK method) for "piping" an input to an output in Java than the following?

public void pipe(Reader in, Writer out) {
    CharBuffer buf = CharBuffer.allocate(DEFAULT_BUFFER_SIZE);
    while( in.read(buf) >= 0 ) {
      out.append(buf.flip());
      buf.clear();
    }
}

[EDIT] Please note the Reader and Writer are given. The correct answer will demonstrate how to take in and out and form a pipe (preferably with no more than 1 or 2 method calls). I will accept answers where in and out are an InputStream and an OutputStream (preferably with a conversion from/to Reader/Writer). I will not accept answers where either in or out is a subclass of Reader/InputStream or Writer/OutputStrem.

+1  A: 

Take a look at java.io.PipedInputStream and PipedOutputStream, or PipedReader/PipedWriter from the same package.

From the Documentation of PipedInputStream:

A piped input stream should be connected to a piped output stream; the piped input stream then provides whatever data bytes are written to the piped output stream. Typically, data is read from a PipedInputStream object by one thread and data is written to the corresponding PipedOutputStream by some other thread. Attempting to use both objects from a single thread is not recommended, as it may deadlock the thread. The piped input stream contains a buffer, decoupling read operations from write operations, within limits. A pipe is said to be broken if a thread that was providing data bytes to the connected piped output stream is no longer alive.

Einar
Is there a way to build a PipedInputStream from a given InputStream (or Reader)?
Chris Conway
I believe you can do something like "new PipedInputStream(theInputStreamInstance)" (i.e, "wrap InputStream with a PipedInputStream).
Chry Cheng
Sorry, leapt before I looked. :( Seems that there is no way to take an existing stream and turn it into a piped stream. A PipedInputStream must be tied to a PipedOutputStream. If you want, you can just transfers bytes from an InputStream to a PipedOutputStream that is tied to a PipedInputStream.
Chry Cheng
+1  A: 

The only optimization available is through FileChannels in the NIO API: Reads, Writes. The JVM can optimize this call to move the data from a file to a destination Channel without first having to move the data to kernel space. See this article for details.

Heath Borders
How would I obtain a FileChannel from a Reader, Writer, InputStream, or OutputStream?
Chris Conway
+8  A: 

IOUtils from the Apache Commons project has a number of utilily methods that do exactly what you need.

IOUtils.copy(in, out) will perform a buffered copy of all input to the output. If there is more than one spot in your codebase that requires Stream or Reader/Writer handling, using IOUtils could be a good idea.

Henning
Wow. Apache Commons is a really impressive project. They scratch all my itches before I even notice them.
Chris Conway
+1 for Apache Commons
Frederic Morin