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());

See also: Converting an OutputStream to an InputStream

 

Advertisements

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s