如何在流中写“按下键”?

时间:2011-02-08 16:56:54

标签: java interface process

对不起这个奇怪的标题......

我有以下情况:我希望我的Java程序与外部控制台进行交互。为了将各个命令“发送”到该控制台,我需要模拟普通控制台上的“按下键”。为了澄清我想要的东西,假设mysql没有其他API,我需要通过控制台进行交互。虽然这不是我的实际问题,但它足够接近。

我有以下代码:

        String command = "/usr/local/mysql/bin/mysql";
        Process child = Runtime.getRuntime().exec(command);

        StreamGobbler gobbler = new StreamGobbler(child.getInputStream());
        gobbler.start();

        BufferedWriter out = new BufferedWriter(new OutputStreamWriter(child.getOutputStream()));
        out.write("help");
        // here enter key needs to be pressed
        out.flush();
        // out.close();

如果执行out.close()的调用,一切都很好。但是,当然,这样我只能发送一个命令,这不是我想要的。但是如果省略out.close(),则其他程序永远不会执行该命令。我的猜测是它仍然等待命令“完成”,这在普通控制台上将按Enter键完成。 out.write(System.getProperty("line.separator"));out.newLine();(相同)不能解决问题,out.write("\r\n");out.write((char) 26);(EOF)也不会解决问题。

当然,可能是,我完全错了(即错误的做法)。那么我会很感激指向正确的方向......

对此表示高度赞赏的任何帮助。

3 个答案:

答案 0 :(得分:7)

以下代码在使用Java 1.6.0_23的Windows 7和使用Java 1.6.0_22的Ubuntu 8.04上都能正常工作:

public class Laj {

  private static class ReadingThread extends Thread {
    private final InputStream inputStream;
    private final String name;

    public ReadingThread(InputStream inputStream, String name) {
      this.inputStream = inputStream;
      this.name = name;
    }

    public void run() {
      try {
        BufferedReader in = new BufferedReader(
            new InputStreamReader(inputStream));
        for (String s = in.readLine(); s != null; s = in.readLine()) {
          System.console().writer().println(name + ": " + s);
        }
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }

  public static void main(String[] args) throws Exception {
    String command = "psql -U archadm arch";
    final Process child = Runtime.getRuntime().exec(command);
    new ReadingThread(child.getInputStream(), "out").start();
    new ReadingThread(child.getErrorStream(), "err").start();
    BufferedWriter out = new BufferedWriter(
        new OutputStreamWriter(child.getOutputStream()));
    out.write("\\h");
    out.newLine();
    out.flush();
    out.write("\\q");
    out.newLine();
    out.flush();
  }

}

newLine()与编写平台线分隔符相同。正如人们所预料的那样,它会打印出“out:”之前的帮助,然后退出。如果我不发送“\ q”,它不会退出(显然),但仍会打印帮助。使用“\ r \ n”或“\ r”而不是平台行分隔符对我来说不是一个好主意,因为这样的命令行实用程序通常会检测到它们没有从终端获取输入并假设它是本机文本格式(想想“psql< script.sql”)。好的软件应该正确检测并接受所有合理的行结尾。

答案 1 :(得分:0)

out.write((char) 13)怎么样?请参阅此Wikipedia文章。我没有足够的代码来为您测试。

答案 2 :(得分:0)

您也可以尝试查看此API

http://download.oracle.com/javase/6/docs/api/java/io/Console.html

根据我的经验,我从未尝试过比从Process API运行一个流程更多的事情。您似乎想要输入多个命令,我认为此API可能会让您这样做。

编辑:找到一个教程来帮助你。 http://download.oracle.com/javase/tutorial/essential/io/cl.html

希望这有帮助,