作为管道写入 Java Process/ProcessBuilder 的 OutputStream

Writing to the OutputStream of Java Process/ProcessBuilder as pipe

我在将数据从 java 发送到 ProcessBuilder/Process 创建的 (linux) 子进程时遇到问题。

仅基于 shell 的基本示例如下所示并且工作正常。

echo "hello world" | cat - >/tmp/receive.dat

现在,我想用 java 程序替换 echo "hello world",该程序应在内部创建一个新进程(cat - >/tmp/receive.dat),然后向其发送数据。

我尝试了以下操作,但文件 /tmp/receive.dat 保持不变:

String[] cmdArray = { "/bin/cat", "-", ">/tmp/receive.dat" };
ProcessBuilder builder = new ProcessBuilder (cmdArray);
builder.directory (new File ("/tmp"));
Process p = builder.start ();
OutputStream pos = p.getOutputStream ();

byte [] bytes = "hello world".getBytes ();
pos.write (bytes);
pos.close ();
p.waitFor ();

在 Windows 下也会发生同样的情况,当然使用经过改编的 cmdArray:

cmd /c type con >c:\tmp\receive.dat

从 java 直接打印到 system.out 是别无选择的方法,因为应该在 java 程序的生命周期内调用许多子进程。

感谢任何帮助! 通博

这里的问题是 /bin/cat 实际上并没有写入文件,它只是写入标准输出。输出重定向 >/tmp/receive.dat 实际上是由 shell 执行的,但是您通过以这种方式调用 cat 来绕过 shell。

如果您想要实现的只是一个写入文件的 OutputStream,那么通过标准 java I/O(例如 FileOutputStream 和朋友)来实现就是您想要的。它也是跨平台的(即 Windows 友好),不像任何依赖于 shell.

的东西

关于关于由于子进程不能仅从 java 写入标准输出的评论 - 您调用的任何子进程都可以从其父进程继承标准输出(java 进程 - 看在 ProcessBuilder.Redirect.INHERIT)。因此,即使您从 java 调用子进程,将所有输出重定向到文件仍应以与初始示例相同的方式工作(其中 java 程序替换了 echo 命令)。

您可能需要 ProcessBuilder#redirectOutput(File),因为 > 功能不是 cat 的功能,而是调用 cat 的功能(在我们的意义上,进程构建器)。