Java:多次写入和读取同一进程

时间:2017-02-28 23:01:18

标签: java process

我已经经历了这么多相关的StackOverflow问题,以至于我迷失了这些问题,而且我已经用多种方式编码,但似乎没有一个方法可以解决这个问题。适用于我:如何在同一时间接收来自同一进程的输入的同时,将输出发送到同一命令并进行多次处理? (有关类似问题,请参阅Input various strings to same process in Java,但结论只有理论上的答案。) 命令(命令行,来自C ++可执行文件)加载一个大文件,然后我想非常快速地向它发送输入,找回答案,在其间做其他事情,然后发送不同的输入并得到相应的答案。将其乘以数千或数百万次。

一个实现,包含线程:

ProcessBuilder pb = new ProcessBuilder(command.split(" "));
kenLMProcess = pb.start();
KenLMInThread lmInput = new KenLMInThread(kenLMProcess.getInputStream());
KenLMInThread lmError = new KenLMInThread(kenLMProcess.getErrorStream());
KenLMOutThread lmOutput = new KenLMOutThread(kenLMProcess.getOutputStream());
lmOutput.inStr = "Test . \n";
lmInput.start();
lmOutput.start();
lmError.start();
lmOutput.join();
lmInput.join();
lmError.join();
outStr = lmInput.newStr;

但是join会一直等到线程结束。如果我不想等到它结束怎么办?我似乎无法弄清楚如何使用wait()来达到这个目的。对于我来说,每次查询命令时,我都不必保持打开和关闭新的输出流和输入流。但至少比每次启动一个新的ProcessBuilder更好。

这里是KenLMOutThread的run():

public void run() {
    try {
        pw.write(inStr+"\n");
        pw.write('\n');
    } catch (Exception e) {
        System.out.println("Error while inputting to KenLM.");

        e.printStackTrace();
    } finally {
        pw.flush();
        try {
            pw.flush();
            bw.close();
        } catch (IOException e) {
            e.printStackTrace();
    }
}

据说冲洗应该让它继续前进,并且" \ n"最后应该有所帮助,但它只是挂起,除非我使用close。如果我使用close,我就不能再使用OutputStream了。我也无法从Process创建一个新的OutputStream。

如果有帮助,这里有一个更简单的实现,包含所有内容(取自How to send EOF to a process in Java?): 请注意,使用close(),使用flush()而不使用close()会导致程序挂起。

public static String pipe(String str, String command2) throws IOException, InterruptedException {
    Process p2 = Runtime.getRuntime().exec(command2);
    OutputStream out = p2.getOutputStream();
    out.write(str.getBytes());
    out.close();
    p2.waitFor();
    BufferedReader reader
            = new BufferedReader(new InputStreamReader(p2.getInputStream()));
    StringBuilder sb = new StringBuilder();
    String line;
    while ((line = reader.readLine()) != null) {
        sb.append(line + "\n");
    }
    return sb.toString();
}

我尝试过的其他事情:

  • 使用exec():处理kenLMProcess = Runtime.getRuntime()。exec(command);

  • 将命令进程放在自己的线程中:KenLMProcessThread procThread = new KenLMProcessThread(pb.start());

1 个答案:

答案 0 :(得分:0)

如果目标进程挂起除非你关闭输出流,那么问题就在于此:它在执行任何操作之前一直读到流结束。在发送端你无能为力。