java - PipedInputStream、PipedOutputStream 和进程

标签 java multithreading process pipe java.util.concurrent

我正在学习 java PipedInputStream/PipeOutputStream 。

我想读取标准输入(下面的“Source”类)并将其重定向到一个进程(此处为“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

我哪里错了?谢谢。

最佳答案

您只需在代码块之后的 Grep 类的方法 run() 中刷新并关闭操作系统流:

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

并且程序将终止。

关于java - PipedInputStream、PipedOutputStream 和进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22614263/

相关文章:

java - 从Java中的文本中删除大空间

java - Java 类中使用的变量阴影是什么?

C#新建进程窗口不隐藏

java - Thread 类如何在另一个类中调用?

multithreading - 哪个Linux系统调用用于获取线程的ID?

java - 如何在 CMD 中打开程序并使用 Java 与其交互

c# - 使用查询字符串打开 html 文件

java - Kotlin 中高阶函数和 SAM 转换的奇怪行为

Java 线程基础

c++ - 从 GetQueuedCompletionStatus 解除阻止