如何使用 java 在外部控制台应用程序中多次写入?

How to write multiple times in external console application using java?

我需要与外部 C++ 控制台程序对话(读取输出和写入输入)。我使用 Thread 从应用程序中读取(它可以工作),但是当它需要输入时,它只在第一次工作,然后流可能保持为空,并且它不接收第二个输入(并且外部程序关闭)。

我正在使用的应用程序是一个用 C++ 编写的简单 .exe:

  1. 打印"Insert first input"
  2. 扫描输入1
  3. 打印输入1
  4. 打印"Insert second input"
  5. 扫描输入2
  6. 打印输入2

主要class:

    import java.io.*;
    import java.util.Scanner;
    public class ExampleCom {

    public static Communication com = new Communication();

    public static void main(String[] args) 
    {
        Scanner in = new Scanner(System.in);
        String s;

        com.read();
        while(true)
        {
            s = in.nextLine();
            com.write(s);
        }
    }

通讯class:

    public class Communication
    {
        Process p;
        OutputStream writer;
        public InputStream reader = null;
        Read r; //Class that with a loop read all exe input

        Communication()
        {   
            try{
                p = Runtime.getRuntime ().exec ("C:\esempio.exe");
                writer = p.getOutputStream();
                reader = p.getInputStream();
            }catch(Exception e){}
        }

        public void read()
        {
            r = new Read();
            Thread threadRead = new Thread(r);
            threadRead.start();
        }

        public void write(String s)
        {
            try{
                writer.write(s.getBytes());
                writer.flush();
                writer.close();
            }catch(Exception e){}
        }
    }

如何在外部应用程序需要时发送我的字符串(如 "writer.write('hello')")?

问题是在您的 write() 方法中,您有行

            writer.close();

这意味着在第一次调用它之后,您将关闭 C++ 的输入流。就它而言,它会在您第一次输入后看到 "end of file" 标记。

您应该做的是将 close() 放在一个单独的方法中,并且只有在您完成该过程后才调用该方法。

现在,由于您的目标程序需要文本输入,并且只有在它到达行尾时才会解释输入(根据您对我评论中问题的回答),您应该提供该行尾 -行。

我认为更好的方法是为该输出流使用 PrintWriter,并像使用 System.out.println() 一样自然地使用,而不是进行原始字节写入。它还可以节省 flush() 部分。

当您看到您的程序在您 close() 之前不读取输入时,您正在错误地解释它。它没有等待 - 它会在您调用 flush() 后立即发送。但是 C++ 等待文件结束或行结束,并且由于您没有给它一个行结束,那么只有 close() 将它发送到文件结束, 使其接受输入。但是你不能再发送任何进一步的数据。

所以解决方案是,首先,将您的 writer 定义为 PrintWriter。而不是

OutputStream writer;

使用

PrintWriter writer;

而不是

            writer = p.getOutputStream();

使用

            writer = new PrintWriter(p.getOutputStream(), true);

那里的 true 会在您使用 println() 命令时自动刷新。

现在,您的写入方法应该是:

    public void write(String s)
    {
        writer.println(s);
    }

请注意 PrintWriter 不会产生异常,因此如果您关心错误,则必须使用 checkError().

检查它们

当然,正如我之前提到的,在单独的方法中使用 close()

因为write()方法可能会抛出IOException,建议在finally block.Place 方法中调用close()方法,在try子句外调用writer.close()方法:

finally {
if(writer != null) {
    writer.close();
}