Multiple quotes cause PipedOutputStream/OutputStreamWriter to fail

I stumbled over a very strange behavior with the PipedOutputStream when I was trying to copy an OutputStream to an InputStream. See also How to write an nt:file programmatically

Here is a small unit test method:

@Test
public void pipeTest() {
    PipedInputStream pin = null;
    try {
        pin = new PipedInputStream();
        PipedOutputStream pout = new PipedOutputStream(pin);
        OutputStreamWriter writer = new OutputStreamWriter(pout);
        for (int i = 0; i < 100; i++) {
            writer.write("\"Test\";" + i + "\n");
            // writer.write("\"Test\";" + "\"" + i + "\"\n");
        }

        writer.close();
        pout.close();

        System.out.print(IOUtils.toString(pin));
    } catch (IOException e) {
        System.out.print(e);
    } finally {
        IOUtils.closeQuietly(pin);
    }

}

This works well and prints out 100 rows. If you uncomment the second write statement and comment out the first, writer.close() gets stuck and never finishes. It seems to have problem with the second set of quotes \". Has anyone and idea why this is the case and how to circumvent it?

Jon Skeet
people
quotationmark

This has nothing to do with the quotes - and everything to do with how much data you're writing. To demonstrate this, you can get rid of the writer and the loop entirely, and just use:

pout.write(new byte[1024]);

Or keep your existing code, but see that this works (because it writes 1000 bytes):

writer.write("0123456789");

but this doesn't (because it tries to write 1100 bytes):

writer.write("0123456789X");

That works - but if you change it to 1025, it'll hang forever... because the internal buffer is 1024 bytes long by default, and nothing's consuming the stream. (You're not reading from pin until you've finished writing.) As nothing is consuming any of the first 1024 bytes, there's nowhere to put the 1025th byte, so write blocks until there is space.

You could:

  • Change the pipe size when you construct the PipedInputStream, so it's got a bigger buffer
  • Read from the pipe while you're writing - e.g. in a separate thread.

people

See more on this question at Stackoverflow