Java Process builder手动管道 [英] Java Process builder manually pipe

查看:152
本文介绍了Java Process builder手动管道的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在两个进程之间手动管理 I/O,但似乎无法获得任何输出.我包括了这个功能.我一直在测试命令dir | grep".Cmd1 和 Cmd2 是 | 两边的命令我在 Windows 操作系统上.如果命令以 & 结尾那么命令不应该等待另一个执行.

I am trying to manually pipe I/O between two processes and I can't seem to get any output. I included the function. I've been testing the command "dir | grep ". Cmd1 and Cmd2 are the commands on either side of the | and I'm on windows os. If the command ends with & then the commands shouldn't wait for the other to execute.

 private void pipe(String Cmd1, String Cmd2, String[] baseCommand1)
    {
        if(System.getProperty("os.name").toLowerCase().startsWith("windows"))
        {
            if(System.getProperty("os.name").toLowerCase().startsWith("windows"))
            {
                baseCommand1[0] = "cmd.exe";
                baseCommand1[1] = "/c";
            }
            else
            {
                baseCommand1[0] = "sh";
                baseCommand1[1] = "-c";
            }
        }

        try {
            String[] p1Cmd = { baseCommand1[0], baseCommand1[1], Cmd1 };
            String[] p2Cmd = { baseCommand1[0], baseCommand1[1], Cmd2 };

            ProcessBuilder pb1 = new ProcessBuilder(p1Cmd);
            ProcessBuilder pb2 = new ProcessBuilder(p2Cmd);          
            pb1.redirectInput(ProcessBuilder.Redirect.INHERIT);
            pb1.redirectOutput(pb2.redirectInput());
            pb2.redirectOutput(ProcessBuilder.Redirect.INHERIT);


            Process p1 = pb1.start();
            Process p2 = pb2.start();

            java.io.InputStream in = p1.getInputStream();
            java.io.OutputStream out = p2.getOutputStream();

            int c;
            while ((c = in.read()) != -1) {
                System.out.println(c);
                    out.write(c);
            }

            out.flush();
            out.close();


            if(!Cmd2.contains("&"))
            {
                p1.waitFor();
                p2.waitFor();
            }

        }
        catch (Exception ex) {
            System.out.print(ex);
        }
    }




推荐答案

您的子进程是否写入了大量数据?通过 Runtime.exec 或 ProcessBuilder 使用 Process 类的一个常见问题是,如果您不使用子流程生成的大型标准输出(或错误)流,您可能会在 Java 应用程序中阻塞.

Does your sub-process write a lot of data? A common problem with using the Process class via Runtime.exec or ProcessBuilder is that you can block in the Java application if you do not consume large standard output (or error) streams generated by the sub-process.

例如在 jshell 中尝试这个 - 它不会在我的 Windows 10 机器上执行,因为没有消耗 STDOUT 流(并且 C:\Temp 很大)

For example try this in jshell - it will not execute on my Windows 10 machine because STDOUT stream is not consumed (and C:\Temp is big)

var p = Runtime.getRuntime().exec("cmd.exe /c \"dir /s C:\\Temp \"")
p.waitFor()
// DOES NOT END...

但是:如果我添加一个线程来消耗同一个进程的大 STDOUT,一切都很好并且运行得很快:

HOWEVER: if I add a thread to consume the large STDOUT of same Process all is fine and runs quickly:

var p = Runtime.getRuntime().exec("cmd.exe /c \"dir /s C:\\Temp \"")
var buf = new ByteArrayOutputStream(8192);
var stream = p.getInputStream();
Runnable r = () -> {
    byte [] buffer = new byte[1024];
    System.out.println("run() START");
    try {
        int len;
        while ((len = stream.read(buffer)) != -1)
            buf.write(buffer, 0, len);
        stream.close();
    }
    catch (IOException ex) {
        throw new UncheckedIOException(ex);
    }
    finally {
        System.out.println("run() END");
    }
}

new Thread(r).start();
p.waitFor()

System.out.println("Your process returned: "+new String(buf.toByteArray()) );

可能是你的 cmd|cmd 生成了长流,需要服务线程在 waitFor() 之前消费输出

It may be that your cmd|cmd is generating a long stream and you need a service thread to consume the output before the waitFor()

这篇关于Java Process builder手动管道的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆