使用Java与命令行工具进行通信

5

我想在我的Java程序中使用Linux命令行工具。我使用Process类(http://download.oracle.com/javase/6/docs/api/java/lang/Process.html)启动程序并获取输出:

 /* @param args
  * @throws IOException 
  */
 public static void main(String[] args) throws IOException {
    Process proc = Runtime.getRuntime().exec("octave");

    BufferedReader reader = 
        new BufferedReader(new InputStreamReader(proc.getInputStream()));

    BufferedReader errorReader = 
        new BufferedReader(new InputStreamReader(proc.getInputStream()));

    BufferedWriter writer = 
        new BufferedWriter(new OutputStreamWriter(proc.getOutputStream()));

    int c;
    while((c = proc.getInputStream().read()) != -1) {
       System.out.print((char)c);
    }
    System.out.println("End");
 }

我得到了以下输出:
GNU Octave,版本3.0.5版权 (C)2008年John W. Eaton和其他人。 这是免费软件;有关复制条件的源代码,请参见。 绝对没有保修;甚至不适用于特定目的。有关详细信息,请键入“warranty”。
Octave已配置为“i486-pc-linux-gnu”。
有关Octave的其他信息可在http://www.octave.org上找到。
如果您发现此软件有用,请做出贡献。有关更多信息,请访问http://www.octave.org/help-wanted.html 报告错误给(但请先阅读http://www.octave.org/bugs.html以了解如何编写有用的报告)。
有关从以前版本进行更改的信息,请键入“news”。
奇怪的是,如果我在终端中运行octave,则正常输出如下所示:
:〜/ workspace / Console / src / c $ octave GNU Octave,版本3.0.5 版权所有(C)2008年John W. Eaton和其他人。 这是免费软件;有关复制条件的源代码,请参见。 绝对没有保修;甚至不适用于特定目的。有关详细信息,请键入“warranty”。
Octave已配置为“i486-pc-linux-gnu”。
有关Octave的其他信息可在http://www.octave.org上找到。
如果您发现此软件有用,请做出贡献。 有关更多信息,请访问http://www.octave.org/help-wanted.html 报告错误给(但请先阅读http://www.octave.org/bugs.html以了解如何编写有用的报告)。
有关从以前版本进行更改的信息,请键入“news”。
octave:1>
因此,在请求输入的行中发送的字符未发送到我的输入流中。为什么?无法检测到是否需要输入吗?
感谢您的回答!
Heinrich
5个回答

7

*nix系统上的程序可以检测它们是否在与终端或其他流进行通信。许多交互式shell类型的程序会根据此做出不同的反应(例如设置不同的提示符、不读取某些初始化文件甚至根本不启动)。

您可能正在遇到这些情况之一。

此外,也许使用Octave的Java API可能是更容易的方法:例如joPAS


谢谢提供joPAS的链接。我会查看API。 不过,我仍然很好奇为什么我的Java程序中没有出现“octave:1>”字符。 - Erik

2
因为Octave的输出被缓冲了,所以你不会得到提示符 "octave:1> "。如果输出不是交互式设备,许多在Unix/Linux上使用stdio的程序也会这样做。只有当缓冲区被填满(自动刷新)或程序显式地调用fflush(3)刷新缓冲区时,才会接收到输出。
如果你真的想与一个命令行程序进行交互,那么你需要使用一个pty(我不知道是否可能使用Java,因为我从未尝试过)。
下面是"man stdio" 的摘录,其中解释了发生了什么:
  At  program  startup, three text streams are predefined and need not be
  opened explicitly -- standard input (for reading conventional input),
  standard  output  (for  writing conventional input), and standard error
  (for  writing  diagnostic  output).   These  streams  are   abbreviated
  stdin,stdout and stderr.  When opened, the standard error stream is not
  fully buffered;  the  standard  input  and  output  streams  are  fully
  buffered  if  and only if the streams do not to refer to an interactive
  device.

  Output streams that refer to terminal devices are always line  buffered
  by  default;  pending  output  to such streams is written automatically
  whenever an input stream that refers to a terminal device is read.   In
  cases  where  a large amount of computation is done after printing part
  of a line on an output terminal, it is necessary to fflush(3) the stan-
  dard  output  before  going  off  and computing so that the output will
  appear.

2

由于你的问题似乎是Octave特定的,我建议使用Octave的--silent选项,并在一次命令行中传递所有参数。这将解决之前关于启动终端会话的问题。


很不幸,这对我来说是不可能的,因为我想要交互式地将Octave与Java一起使用。 - Erik

1
我终于解决了这个问题:在Linux下,使用带有--interactive选项和最终的--no-line-editing选项的Octave,它起作用了 :)
Heinrich

1

它是否为此提示打开了一个新的文件描述符?

您可能会在Octave源代码(或如果Octave使用该代码,则在Readline源代码中)找到它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接