Stephen Ostermiller's Blog

Convert a Java Writer to a Reader

If you have ever programmed using Java IO, you will quickly run into a situation in which a class creates data on a Writer and you need to send it to another class that expects to read the data from a Reader. You'll soon be asking the question, "How do I convert a Writer to a Reader?"

Nowhere in Java will you find a WriterToReaderConverter class. Luckily, there are several ways to go about this.

Method 1: Buffer the data using a String

The easiest method is to buffer the data using a String. The code will look something like this:

StringWriter out = new StringWriter();
class1.putDataOnWriter(out);
class2.processDataFromReader(
  new StringReader(out.toString())
);

That's it! The Writer has been converted to a Reader.

Method 2: Use pipes

The problem with the first method is that you must actually have enough memory to buffer the entire amount of data. You could buffer larger amounts of data by using the filesystem rather than memory, but either way there is a hard limit to the size of the data that can be handled. The solution is create a thread to produce the data to the PipedWriter. The current thread can then read the data as it comes in.

PipedReader in = new PipedReader();
PipedWriter out = new PipedWriter(in);
new Thread(
  new Runnable(){
    public void run(){
      class1.putDataOnWriter(out);
    }
  }
).start();
class2.processDataFromReader(in);

Method 3: Use Circular Buffers

The two piped streams in method two actually manage a hidden circular buffer. It is conceptually easier to use an explicit Circular Buffer. CircularBuffers offer several advantages:

  • One CircularBuffer class rather than two pipe classes.
  • It is easier to convert between the "buffer all data" and "two threads" approaches.
  • You can change the buffer size rather than relying on the hard-coded 1k of buffer in the pipes.

Multiple Threaded Example of a Circular Buffer

CircularCharBuffer ccb = new CircularCharBuffer();
new Thread(
  new Runnable(){
    public void run(){
      class1.putDataOnWriter(ccb.getWriter());
    }
  }
).start();
class2.processDataFromReader(ccb.getReader());

Single Threaded Example of a Circular Buffer

// buffer all data in a circular buffer of infinite size
CircularCharBuffer ccb = new CircularCharBuffer(CircularCharBuffer.INFINITE_SIZE);
class1.putDataOnWriter(ccb.getWriter());
class2.processDataFromReader(ccb.getReader());

Leave a comment

Your email address will not be published. Required fields are marked *