PipedInputStream,PipedOutputStream和Process

时间:2014-03-24 15:53:04

标签: java multithreading process pipe java.util.concurrent

我正在学习java PipedInputStream / PipeOutputStream。

我想阅读标准输入(下面的'来源'类)并将其重定向到进程(此处为'grep A'), Grep 的输出将被重定向到System.out。

为了在grep之后完成stdout和stderr,我还创建了一个类 CopyTo 来将输入流重定向到输出流。

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();
            }
        }

    }

但是,编译和运行程序不会产生任何输出(程序被冻结)。

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

我哪里错了?感谢。

1 个答案:

答案 0 :(得分:1)

您需要在代码块之后刷新并关闭Grep类的方法run()中的os流:

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

添加以下行:

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

Grep类的run()方法必须如下所示:

@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();
    }
}

命令的输出:

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

将是:

A

程序将终止。