如何使用 java 在外部控制台应用程序中多次写入?
How to write multiple times in external console application using java?
我需要与外部 C++ 控制台程序对话(读取输出和写入输入)。我使用 Thread 从应用程序中读取(它可以工作),但是当它需要输入时,它只在第一次工作,然后流可能保持为空,并且它不接收第二个输入(并且外部程序关闭)。
我正在使用的应用程序是一个用 C++ 编写的简单 .exe:
- 打印"Insert first input"
- 扫描输入1
- 打印输入1
- 打印"Insert second input"
- 扫描输入2
- 打印输入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();
}
我需要与外部 C++ 控制台程序对话(读取输出和写入输入)。我使用 Thread 从应用程序中读取(它可以工作),但是当它需要输入时,它只在第一次工作,然后流可能保持为空,并且它不接收第二个输入(并且外部程序关闭)。
我正在使用的应用程序是一个用 C++ 编写的简单 .exe:
- 打印"Insert first input"
- 扫描输入1
- 打印输入1
- 打印"Insert second input"
- 扫描输入2
- 打印输入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();
}