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.
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.