Hi, I have a small proposal. Usage scenario is as follows.
One generates a char array of data using some process and then immediately this is consumed by another process. There are two ways of doing the same now. 1. Use a CharArrayWriter to accumulate the data generated in the first step. convert it to char[] and then consume the char[] in the next step. 2. Use piped reader writer pair. In both these methods data is written twice. firstly into the intermediate buffer then onto an array that the second step will consume. I have written a class on lines of the piped reader and writer. In this class there is no intermediate buffer. writer writes the data directly into the char array passed by the reader in the read method. Kindly have a look at the class ReaderWriter and ReaderWriterTest (which gives a usage sample). Also one more small proposal. Why don't you have a CharArrayWriter class on the same lines of ByteArrayOutputStream? thanks, nishant
package com.nk.io; import java.io.IOException; import java.io.Reader; import java.io.Writer; /** * This class enables a reader to read a content written by a writter * in a much easier manner than using Piped Writer and Piped Reader. * This is more efficient than the other as the amount of data copy * is halved as there is no intermediate buffer. The data passed by * the writer is written directly into the buffer passed by the * reader methods.<br> * To use this class just instantiate this class, get the reader and * writer in two threads and starts reading from and writing to them * respectively. When finished close the writer and then close the * reader when it returns -1. Skipping and marking is not supported * in reader.<br> * Writer must be closed to complete the reading process. Writing to * a writer when the reader has been closed will throw an IOException. * <br> * Passing a larger buffer into the read method will reduce context * switch between the reader and the writer threads. * * @author Nishant Kumar */ public final class ReaderWriter { private final PrivateReader reader = new PrivateReader(); private final PrivateWriter writer = new PrivateWriter(); private final Object mutex = new Object(); private boolean writerClosed = false; private boolean readerClosed = false; public ReaderWriter() { } /** * Returns the reader. * @return the reader */ public Reader getReader() { return reader; } /** * Returns the writer. * @return the writer. */ public Writer getWriter() { return writer; } private final class PrivateReader extends Reader { private char[] readerBuffer; private int readerOffset; private int readerLength = 0; public void close() { synchronized (mutex) { readerClosed = true; mutex.notify(); } } public int read(final char[] readerBuffer, final int offset, final int length) { if ((offset < 0) || (offset > readerBuffer.length) || (length < 0) || ((offset + length) > readerBuffer.length) || ((offset + length) < 0)) { throw new IndexOutOfBoundsException(); } else if (length == 0) { return 0; } synchronized (mutex) { if (writerClosed) { return -1; } this.readerBuffer = readerBuffer; this.readerOffset = offset; this.readerLength = length; mutex.notify(); while (this.readerLength > 0 && !writerClosed) { try { mutex.wait(); } catch (InterruptedException e) { throw new RuntimeException(e); } } } return this.readerOffset - offset; } public long skip(final long n) { return 0; } public void write(final char[] writerBuffer, int offset, int length) throws IOException { synchronized (mutex) { while (length > 0) { while (this.readerLength == 0 && !readerClosed) { try { mutex.wait(); } catch (InterruptedException e) { throw new RuntimeException(e); } } if (readerClosed) { throw new IOException("Reader has been closed"); } final int lengthToWrite = Math.min(length, this.readerLength); System.arraycopy(writerBuffer, offset, this.readerBuffer, this.readerOffset, lengthToWrite); offset += lengthToWrite; length -= lengthToWrite; this.readerOffset += lengthToWrite; this.readerLength -= lengthToWrite; if (this.readerLength == 0) { mutex.notify(); } } } } } private final class PrivateWriter extends Writer { public void close() { synchronized (mutex) { writerClosed = true; mutex.notify(); } } public void flush() { //no-op } public void write(final char writerBuffer[], final int offset, final int length) throws IOException { if ((offset < 0) || (offset > writerBuffer.length) || (length < 0) || ((offset + length) > writerBuffer.length) || ((offset + length) < 0)) { throw new IndexOutOfBoundsException(); } else if (length == 0) { return; } reader.write(writerBuffer, offset, length); } } }
package nkio; import com.nk.io.ReaderWriter; import junit.framework.TestCase; import java.io.IOException; import java.io.Reader; import java.io.Writer; import java.util.Random; public class ReaderWriterTest extends TestCase { public void testReaderWriter() throws Exception { ReaderWriter readerWriter = new ReaderWriter(); Reader reader = readerWriter.getReader(); Writer writer = readerWriter.getWriter(); String[] strs = new String[10]; String result = createRandomData(strs); Thread writerThread = new Thread(new WriterRunnable(strs, writer)); writerThread.start(); Thread.sleep(100); StringBuffer buffer = new StringBuffer(strs.length * 6); char[] cbuf = new char[4]; int read = 0; while ((read = reader.read(cbuf)) != -1) { buffer.append(cbuf, 0, read); } assertEquals(result, buffer.toString()); } private String createRandomData(String[] strs) { StringBuffer buffer = new StringBuffer(strs.length * 6); Random random = new Random(); for (int i = 0; i < strs.length; i++) { strs[i] = String.valueOf(random.nextInt(100000)); buffer.append(strs[i]); } return buffer.toString(); } private class WriterRunnable implements Runnable { private String[] strs; private Writer writer; public WriterRunnable(String[] strs, Writer writer) { this.strs = strs; this.writer = writer; } public void run() { try { for (int i = 0; i < strs.length; i++) { writer.write(strs[i]); } writer.close(); } catch (IOException e) { throw new RuntimeException(e); } } } }
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]