2011-02-08 2 views
6

Извините за это нечетное звучание ...Как написать «ввести клавишу нажатой» в поток?

У меня есть следующая ситуация: я хочу, чтобы моя программа 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).

Конечно, возможно, что я делаю это совершенно неправильно (т. Е. Неправильный подход). Тогда я был бы признателен за указатель в правильном направлении ...

Любая помощь по этому высоко ценится.

+1

Вы должны потреблять стандартные выходные данные ** и ** стандартные выходные потоки ошибок. Что вы получаете в этих потоках? –

+1

В какой системе вы работаете? Вы используете пути Unix, но попробовали Windows EOF (Ctrl-Z = 26)? Unix EOF - это Ctrl-D (= 4), но, конечно же, это не так. –

+0

@Mark Peters: К сожалению, я должен был добавить gobbler для потока вывода ошибок, но оба потока ничего не получают, если только 'out.close()' выполняется как указано. @Sergey Tachenov: Я работаю на Mac, и Ctrl-D тоже не работает, но спасибо, что указали это. – roesslerj

ответ

7

Следующий код прекрасно работает как на Windows 7 с использованием Java 1.6.0_23 и на Ubuntu 8.04 с использованием Java 1.6.0_22:

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»). Хорошее программное обеспечение должно должным образом определять и принимать все разумные окончания линии.

+0

Спасибо, что разместили свой пример. Поскольку вы делаете в основном то же самое, что и я, разница, вероятно, связана с вызываемым процессом или базовой ОС (MacOSX в моем случае) или даже с Java-версией. Я посмотрю, что я могу узнать, спасибо за ваш ответ! – roesslerj

+0

@roesslerj, вы все равно должны сначала проверить stderr. Может быть глупой ошибкой, которая предотвращает нормальную работу выполняемой команды. Или, возможно, он пытается написать какое-то предупреждение в stderr и блокируется, потому что stderr не загружен, а другая сторона (ваш процесс) ничего не читает. –

+0

Спасибо за доставку этого фрагмента кода. Оказывается, ваш код работает и для меня ... и что у меня была глупая ошибка в пропущенном коде класса StreamGobbler (который по вашей рекомендации я использовал как для stdout, так и для stderr ... Только один незначительный примечание: 'out.write (System.getProperty (" line.separator "));' приводит к тому же, что и вызов out.newLine(); '. – roesslerj

0

Что относительно out.write((char) 13)? См. Статью Wikipedia. У меня недостаточно кода, чтобы проверить это для вас.

+0

Символ возврата каретки в Java обозначается символом '\ r', поэтому я уже пробовал это (см. Текст), но все же спасибо за ввод. – roesslerj

0

Вы также можете попробовать глядя на этот API

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

Из моего опыта, я никогда не пробовал делать ничего больше, чем при запуске одного процесса от процесса API. Похоже, вы хотите ввести несколько команд, я думаю, что этот API может позволить вам это сделать.

EDIT: Найден учебник по этому вопросу, чтобы помочь вам в дальнейшем. http://download.oracle.com/javase/tutorial/essential/io/cl.html

Надеется, что это помогает,

+2

Возможно, я ошибаюсь, но этот API больше похож на то, что вы хотите, когда сами пишете интерактивную консоль. Но это не то, что я хочу сделать; Мне нужно взаимодействовать с такой консолью в виде внешнего процесса. – roesslerj

Смежные вопросы