如何在流中写"按下键"?

roe*_*erj 6 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();
Run Code Online (Sandbox Code Playgroud)

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

当然,可能是,我完全错了(即错误的做法).然后我会欣赏指向正确方向的指针......

对此的任何帮助高度赞赏.

Ser*_*nov 8

以下代码在使用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();
  }

}
Run Code Online (Sandbox Code Playgroud)

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