pipes and pipe streams

 

see also PipedReader class,  PipedWriter class,  PipedInputStream class,  PipedOutputStream class

 

  Java pipe streams are just like real plumbing pipes.  You put things into to a pipe at one end - using write(...) methods.  Then you receive the same things back from the pipe stream at the other end  - using read(...) methods. They come out in FIFO order, first-in first-out, just like from real plumbing pipes.  The ends of pipe streams can be connected using one of two approaches: (1) constructor parameters or (2) a connect(...) method.

 

  This snippet simply writes the A-Z alphabet as 26 separate chars into a pipe using a PipedWriter stream and then immediately reads the letters back individually from the other end of the pipe using PipedReader stream.  It also prints them.

 

import java.io.*;

 

PipedReader pr = new PipedReader( );

String S = "ABCEFGHIJKLMNOPQRSTUVWXYZ";

try {

    PipedWriter pw = new PipedWriter( pr );               // connection created here, in the constructor

    for ( int x = 0;  x < S.length( );  x++ ) {

           pw.write( S, x, 1 );

     }

     for ( int x = 0;  x < 26;  x++ ) {

             System.out.print( (char) pr.read( ) );

      }

} catch (IOException e) { }

 

  You cannot create pipe connections in constructors without using an enclosing try-catch block.  However, there's a way to do the creations without a try-catch block.  First, create the pipe class objects without any connections, and then connect them later with a connect(...) method.  In that case, just the connect(...) method invocation will need the try-catch block. i.e.

 

This snippet repeats the simple example above, but this time using the connect(...) method to make the pipe connection rather than constructor parameters.  Note that neither creation statement is now inside the try-catch block.

 

import java.io.*;

 

PipedReader pr = new PipedReader( );      // no connections are created in the constructors

PipedWriter pw = new PipedWriter( );                        // both statements are outside a try-catch block

String S = "ABCEFGHIJKLMNOPQRSTUVWXYZ";

    try {

           pr.connect( pw );                                               // the connection is now made here

           for ( int x = 0;  x < S.length( );  x++ ) {

                  pw.write( S, x, 1 );

           }

           for ( int x = 0;  x < 26;  x++ ) {

                  System.out.print( (char) pr.read( ) );

           }

     } catch (IOException e) { }

 

  You cannot write to a pipe without having some sort of reader created and connected to it.  In other words, both ends must be present and already connected for the writing end to work.

 

  You cannot switch to another reader, to which the pipe was not originally connected, once you are done writing to a pipe. 

 

  You cannot read back from the pipe if you close the reader.  You can close the writing end successfully, however, and still read from the pipe.

 

  You cannot read back from the pipe if the thread which wrote to it ends.

 

The example below shows one thread writing to a pipe stream and then passing both ends of the pipe to a second thread, which reads what's in the pipe stream until end of file.  If the sleep( ) statement in the first thread is commented out, the first thread will end before the second thread can read from the pipe, and an IOException of "write end (is) dead" will occur.

 

import java.io.*;

 

public class PipeThread1 {

    public static void main( String[ ] args ) {                             

        PipeThread1 P = new PipeThread1( );

    }

 

    public PipeThread1( ) {

        try {

            PipedReader pr1 = new PipedReader( );

            PipedWriter pw1 = new PipedWriter( pr1 );

            String S = "123456789";

 

            pw1.write( S );

            Thread pt2 = new Thread( new PipeThread2( pw1, pr1 ) );         

 

            pt2.start( );

            Thread.sleep(3000);                          // *** sleep to give PipeThread2 a chance to run ***

            return;

        } catch (Exception e) {

            System.out.println("PipeThread1 Exception: " + e);

        }

    }

}

 

class PipeThread2  implements Runnable {

    PipedReader pr2;

    PipedWriter pw2;

   

    public PipeThread2( PipedWriter pw, PipedReader pr ) {

        pw2 = pw;

        pr2 = pr;

    }

 

    public void run( ) { 

        try {

            while ( true ) {

                char c = (char) pr2.read( );           // read a char

                if ( c != 0xffff ) {                             // check for -1 indicating end of file

                    System.out.print( c );

                    continue;

                } else {

                    pr2.close( );

                    pw2.close( );

                    break;

                }

            }

        } catch (Exception e) {

            System.out.println(" PipeThread2 Exception: " + e);

        }

    }

}