Question

I'm learning the java PipedInputStream/PipeOutputStream .

I'd like to read stdin (the 'Source' class below) and redirect it to an Process ( here 'grep A'), the output of Grep would be redirected to System.out.

To consumme stdout and stderr after grep, I also created a class CopyTo to redirect an inputstream to an outputstream.

import java.io.*;
class Test
    {
    private static class Source
        implements Runnable
        {
        private PipedOutputStream pipedOutputStream=new PipedOutputStream();
        private InputStream in;

            Source(InputStream in) throws IOException
                {
                this.in=in;
                }


            @Override
            public void run()
                {
                try
                    {
                    int c;
                    while((c=this.in.read())!=-1)
                        {
                        pipedOutputStream.write(c);
                        }
                    pipedOutputStream.flush();
                    pipedOutputStream.close();
                    }
            catch(Exception err)
                {
                err.printStackTrace();
                }
                }
        }

    private static class Grep
        implements Runnable
        {

        private PipedInputStream pipeInPipedInputStream;

        public Grep(Source src) throws IOException
            {
            this.pipeInPipedInputStream=new PipedInputStream(src.pipedOutputStream);
            }

            @Override
            public void run()
                {
            try {
                Process proc=Runtime.getRuntime().exec(new String[]{
                    "/bin/grep",
                    "A"});
                OutputStream os=proc.getOutputStream();


                Thread t1=new Thread(new CopyTo(proc.getErrorStream(),System.err));
                Thread t2=new Thread(new CopyTo(proc.getInputStream(),System.out));
                t1.start();
                t2.start();
                int c;
                while((c=this.pipeInPipedInputStream.read())!=-1)
                    {   
                    os.write((char)c);
                    }

                t1.join();
                t2.join();
                } 
            catch (Exception e) {
                e.printStackTrace();
                }
                }
        }

    private static class CopyTo implements Runnable
        {
        private InputStream in;
        private OutputStream out;
        CopyTo(InputStream in,OutputStream out)
            {
            this.in=in;
            this.out=out;
            }
        @Override
        public void run() {
            try {
                int c;
                while((c=in.read())!=-1)
                    {
                    out.write(c);
                    }
                }
            catch (Exception e)
                {
                e.printStackTrace();
                }
            }
        }


    public static void main(String[] args)
        {
        try
            {
            Source src=new Source(System.in);
            Thread t1=new Thread(src);
            Thread t2=new Thread(new Grep(src));
            t1.start();
            t2.start();
            }
        catch(Exception err)
            {
            err.printStackTrace();
            }
        }

    }

however, compiling and running the program produces no output (and the program is frozen).

$ javac Test.java && echo -e "A\nT\nG\nC" | java Test

Where am I wrong ? Thanks.

Was it helpful?

Solution

Your simply need to flush and close os stream in method run() of the Grep class after the block of code:

while((c=this.pipeInPipedInputStream.read())!=-1)
{   
    os.write((char)c);
}

add this lines:

os.flush();
os.close();

And your method run() of the Grep class must look like:

@Override
public void run()
{
    try {
        Process proc=Runtime.getRuntime().exec(new String[]{
             "/bin/grep",
             "A"});
        OutputStream os=proc.getOutputStream();

        Thread t1=new Thread(new CopyTo(proc.getErrorStream(),System.err));
        Thread t2=new Thread(new CopyTo(proc.getInputStream(),System.out));
        t1.start();
        t2.start();
        int c;
        while((c=this.pipeInPipedInputStream.read())!=-1)
        {   
             os.write((char)c);
        }

        //missing lines of code
        os.flush();
        os.close();

        t1.join();
        t2.join();
    } 
    catch (Exception e) {
        e.printStackTrace();
    }
}

The output of the command:

$ javac Test.java && echo -e "A\nT\nG\nC" | java Test

will be:

A

and program will terminated.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top