Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/400.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 并发运行外部程序并通过stdin/stdout与之通信_Java - Fatal编程技术网

Java 并发运行外部程序并通过stdin/stdout与之通信

Java 并发运行外部程序并通过stdin/stdout与之通信,java,Java,我希望能够与Java代码同时运行外部程序,也就是说,我希望启动程序,然后将控制权返回给调用方法,同时保持外部程序运行。然后,Java代码将继续生成输入,并将其发送到外部程序并接收输出 我不想继续加载外部程序,因为它有很高的开销。实现这一目标的最佳方式是什么?谢谢 请查看ProcessBuilder。设置ProcessBuilder并执行start后,您将拥有一个进程的句柄,您可以向该句柄输入和读取输出 下面是一个让您开始学习的片段: ProcessBuilder pb = new Process

我希望能够与Java代码同时运行外部程序,也就是说,我希望启动程序,然后将控制权返回给调用方法,同时保持外部程序运行。然后,Java代码将继续生成输入,并将其发送到外部程序并接收输出


我不想继续加载外部程序,因为它有很高的开销。实现这一目标的最佳方式是什么?谢谢

请查看
ProcessBuilder
。设置
ProcessBuilder
并执行
start
后,您将拥有一个
进程的句柄,您可以向该句柄输入和读取输出

下面是一个让您开始学习的片段:

ProcessBuilder pb = new ProcessBuilder("/bin/bash");
Process proc = pb.start();

// Start reading from the program
final Scanner in = new Scanner(proc.getInputStream());
new Thread() {
    public void run() {
        while (in.hasNextLine())
            System.out.println(in.nextLine());
    }
}.start();

// Write a few commands to the program.
PrintWriter out = new PrintWriter(proc.getOutputStream());
out.println("touch hello1");
out.flush();

out.println("touch hello2");
out.flush();

out.println("ls -la hel*");
out.flush();

out.close();
输出:

-rw-r--r-- 1 aioobe aioobe 0 2011-04-08 08:29 hello1
-rw-r--r-- 1 aioobe aioobe 0 2011-04-08 08:29 hello2

您可以使用Runtime.getRuntime().exec(…)启动外部应用程序


要将数据发送到外部程序,您可以在进程输出流上发送数据(从exec获得一个进程对象),也可以打开套接字并以这种方式进行通信。

我认为Javadoc for类会对您有所帮助。需要注意的是,您可以从进程中获取输入和输出流,以便在进程运行时与之通信。

我支持有关使用
ProcessBuilder
的答案。如果您想了解更多有关这方面的详细信息,以及为什么您更喜欢它而不是
Runtime.exec()
,请参阅此。它还显示了如何使用线程与外部进程通信。

由于阻塞,我在尝试通过stdin/stdout与外部进程实现双向通信时遇到了问题。最后我找到了一个简单而优雅地解决问题的方法;这一要点实际上是基于一个假设

查看示例代码的另一个答案,但其核心思想是设置一个用于读写的事件循环(10毫秒睡眠的循环),并使用低级流操作,这样就不会发生缓存和阻塞——只有在知道另一个进程实际上写了东西(通过)时才尝试读取


这导致了一种有点奇怪的编程风格,但代码比使用线程时简单得多,而且工作做得很好。

我尝试过这样做,但由于我的外部程序等待stdin,它会阻塞,因此我无法从调用方法获得控制权。我需要控制,因为外部程序的输入是稍后生成的。可能是外部程序的读取阻塞了。你需要把它放在一个单独的线程中,除非你确切知道什么时候读。谢谢!您的答案正是我想要的。您描述的是
Runtime.exec()
(和`ProcessBuilder)的默认行为。阅读拉尔森:我真的,真的,建议不要在溪流上制作任何东西:否则你会陷入一个充满伤害和痛苦的世界。我在更多的机器上创建的外部进程可能比这里的任何人都多(也就是说:在许多用户系统上提供的应用程序上,并不断创建外部进程),所以我对我所说的有一点了解。我使用临时文件进行流程通信(网络有问题,比如触发AV通知,这可能会让用户感到不安,试图从Java操作stdin/out是一种错觉)。