gpt4 book ai didi

java - 读取文件以处理 Stdin ProcessBuilder

转载 作者:行者123 更新时间:2023-11-30 06:58:51 25 4
gpt4 key购买 nike

如何使用 ProcessBuilder 将文件通过管道传输到进程的标准输入中?我正在读取流的程序是用 C 编写的,但我对它一无所知。

这里是相关的java:

  ProcessBuilder pb = new ProcessBuilder("./program").inheritIO();
Process p = pb.start();
DataInputStream din = new DataInputStream(new FileInputStream("./my-file.txt"));
byte[] dinBytes = new byte[din.available()];
din.readFully(dinBytes);
din.close();
OutputStream os = p.getOutputStream();
os.write(dinBytes);
os.close();
int rc = p.waitFor();
System.out.println("RC: " + rc);

返回以下错误:

java.io.IOException: Stream closed
at java.lang.ProcessBuilder$NullOutputStream.write(ProcessBuilder.java:434)
at java.io.OutputStream.write(OutputStream.java:116)
at java.io.OutputStream.write(OutputStream.java:75)
at Test.main(Test.java:14)
$ input in flex scanner failed

最佳答案

错误的原因是在构建流程时调用了 .inheritIO()。这导致所有进程的标准文件描述符都继承自 Java 进程。 documentation说:

This is a convenience method. An invocation of the form

pb.inheritIO()

behaves in exactly the same way as the invocation

pb.redirectInput(Redirect.INHERIT)   
.redirectOutput(Redirect.INHERIT)
.redirectError(Redirect.INHERIT)

redirectInput(Redirect) 的文档说:

If the source is Redirect.PIPE (the initial value), then the standard input of a subprocess can be written to using the output stream returned by Process.getOutputStream(). If the source is set to any other value, then Process.getOutputStream() will return a null output stream.

因此,基本上,默认情况下在 Java 进程和构建的进程之间存在管道,这样您就可以将数据从程序推送到进程。但是你从管道中释放了进程的标准输入并让它等待来自用户控制台的输入,但是你试图将它视为它仍然是管道的一部分,并让你的管道结束以便推送里面的数据。您会得到一个空输出流,一旦您尝试向其中输入内容,就会出现异常。

所以你不应该打那个电话。由于您需要从文本文件输入,最简单的做法实际上是将该输入流直接重定向到文件。同样,重定向会破坏管道 - 但您不需要它,因为重定向实际上可以满足您的需求:

// Take input from a file, output and error go to user console
pb = new ProcessBuilder("./program")
.redirectInput(new File("./my-file.txt"))
.redirectOutput(Redirect.INHERIT)
.redirectError(Redirect.INHERIT);
Process p = pb.start();
int rc = p.waitFor();

另一种方法,如果你想输入多个文件,是保持管道到进程标准输入,但使用 Files 复制文件:

pb = new ProcessBuilder("./program")
.redirectOutput(Redirect.INHERIT)
.redirectError(Redirect.INHERIT);
Process p = pb.start();
OutputStream os = p.getOutputStream();
Files.copy( Paths.get("./my-file-1.txt"), os );
Files.copy( Paths.get("./my-file-2.txt"), os );
// more files

os.close();
int rc = p.waitFor();

关于 DataInputStream:它是一种 InputStream,用于处理从 DataOutputStream 写入的二进制数据 - 具有整数、 double 等以二进制形式编写。当然,与任何 InputStream 一样,您可以按原样从中读取字节。但为此,您实际上不需要将其包装在 DataInputStream 中。

关于java - 读取文件以处理 Stdin ProcessBuilder,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32212095/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com