当前位置: 首页 > 知识库问答 >
问题:

在Java中重用输入流到进程

宰父淳
2023-03-14

我正在使用ProcessBuilder,使用Java从C程序输入和接收信息。在启动流程一次之后,我希望能够输入新字符串并接收它们的输出,而不必重新启动整个流程。这是我迄今为止采取的方法:

public void getData(String sentence) throws InterruptedException, IOException{
        InputStream stdout = process.getInputStream();
        InputStreamReader isr = new InputStreamReader(stdout);
        OutputStream stdin = process.getOutputStream();
        OutputStreamWriter osr = new OutputStreamWriter(stdin);
        BufferedWriter writer = new BufferedWriter(osr);
        BufferedReader reader = new BufferedReader(isr);

        writer.write(sentence);
        writer.close();

        String ch = reader.readLine();
        preprocessed="";
        while (ch!=null){
            preprocessed = preprocessed+"~"+ch;
            ch = reader.readLine();
        }

        reader.close();
}

每次我想向正在运行的进程发送输入时,我都调用这个方法。然而,有一个问题:第一次我发送输入时,它很好,输出被完美地接收到。然而,第二次我调用它时,我收到了错误

java.io.IOException: Stream closed

这是出人意料的,因为当再次调用该方法时,理论上一切都会重新创建。此外,删除关闭BufferedWriter的行会导致代码停在下一行,就像BufferedReader正在等待BufferedWriter关闭一样。

最后一件事——即使我创建了一个新的BufferedWriter,并指示该方法在第二次调用时使用它,我也会得到同样的异常,这一点我完全不理解。

有没有办法解决这个问题?

非常感谢!

共有2个答案

范安歌
2023-03-14

不要一直试图创建和关闭你的流,因为一旦你关闭它,它就会永远关闭。创建一次,然后在getData(…) 方法使用现有的流。只有当你完全处理完你的流或它们的包装类后,才能关闭它们。

请注意,您应该在同一方法中打开和关闭Streams,因此可能需要其他方法或类来帮助您处理Streams。考虑为此创建一个Runnable类,然后从另一个线程中的Streams中读取。也不要忽略错误流,因为这可能会发送您需要完全理解这里发生了什么的关键信息。

景靖琪
2023-03-14

发生意外的IOExctive是因为当Readers和Writers关闭时,它们会依次关闭底层流。

当你第一次调用你的方法时,一切似乎都正常。但是您关闭了writer,它关闭了流程输出流,从流程的角度来看,它关闭了stdin。不确定你的C二进制文件是什么样子,但当它处理完所有的输入后,它可能会愉快地退出。

因此,对方法的后续调用不起作用。

在Reader方面有一个单独但类似的问题。您调用readLine(),直到它返回null,这意味着Reader已经感觉到流的结束。但是只有当过程完全完成其标准输出时,这种情况才会发生。

当你处理完一个工作单元(不管你所说的“句子”是什么意思)时,你需要某种方式来识别,而不需要等待整个流结束。流没有输出之间逻辑暂停的概念。它只是一个连续的流。Reader和Writer只是一个薄薄的表皮,用来缓冲字节和字符,但基本上与流一样工作。

也许输出可以有分隔符。或者,您可以在实际发送输出之前发送每个输出块的长度,并以这种方式区分输出。或者你可能提前知道每个响应需要多长时间?

你只有一次机会穿过溪流。因此,它们必须比这种方法更有效。如果想避免每次都重新启动流程,就不能打开和关闭流。(进程还有其他通信方式,例如套接字,但这可能超出了范围。)

在一个正交的注释中,当您累积输出时,附加到StringBuilder通常比字符串串联的大循环更有效。

您可能还有一些线程检查过程。exitValue()或以其他方式确保流程按预期工作。

 类似资料:
  • 问题内容: 我在try / catch块中有以下代码 我的问题是,当我必须在finally块中关闭这些流时,是否必须关闭所有3个流,或者仅关闭 befferedreader 会关闭所有其他流? 问题答案: 按照惯例,包装流(用于包装现有流)在关闭时会关闭基础流,因此仅在示例中必须关闭。而且,关闭已经关闭的流通常是无害的,因此关闭所有3个流都不会受到伤害。

  • 现在准备要构建一个工具,用来把前面idata.txt里的数据按group分行显示,就像这样: 2 9 10 3 1 2 3 我们可以借助语法分析树的Listener机制来对词法分析结束后生成的记号流进行改写,我们不需要实现每一个Listener接口方法,只需要在捕获到group的时候把换行符插到它末尾就行。实现改写的代码如下所示: import org.antlr.v4.runtime.Toke

  • 我有一个输入流,其中包含XML数据,我想在返回输入流之前对其进行解析。 当然,我可以将流保存为字节数组,并从中返回一个新的InputStream,或者 在“myObj”上创建第二个InputStream。 但是有什么方法可以“即时”解析流吗? 编辑: 基本上,我正在寻找一种在解析后重用流的方法。在不消耗流的情况下解析流,分别在解析后重置流。 解决方案: 我找到的解决方案是使用BufferedInp

  • 本小节将会介绍基本输入输出的 Java 标准类,通过本小节的学习,你将了解到什么是输入和输入,什么是流;输入输出流的应用场景,File类的使用,什么是文件,Java 提供的输入输出流相关 API 等内容。 1. 什么是输入和输出(I / O) 1.1 基本概念 输入/输出这个概念,对于计算机相关专业的同学并不陌生,在计算中,输入/输出(Input / Output,缩写为 I / O)是信息处理系

  • 我有这个输入流: 如何将其转换为ServletInputStream? 我试过: 但不工作。 编辑: 我的方法是这样的: 我正在尝试将我的所有请求转换为小写。

  • 问题内容: 我下面有以下代码示例。你可以在其中输入的命令,即回显结果。但是,先读后。其他输出流不起作用? 为什么会这样或我做错了什么?我的最终目标是创建一个线程计划任务,该任务定期执行对/ bash的命令,因此必须一前一后工作,而不能停止工作。我也一直在经历错误的任何想法? 谢谢。 问题答案: 首先,我建议更换生产线 与线 ProcessBuilder是Java 5中的新增功能,它使运行外部进程更