2013-09-24 3 views
2

Я не знаю, возможно ли это, но вы можете попробовать.
Я выполнения небольшой код на языке Perl в моей программе Java, как этотНепрерывный отклик от perl к java-программе

private void executePerlCode() { 
    Process process; 
    ProcessBuilder processBuilder; 
    BufferedReader bufferedReader = null; 
    try { 
     // this line is used to execute the perl program 
     processBuilder = new ProcessBuilder("perl", "D:\\test\\loop.pl"); 
     process = processBuilder.start(); 

     // To get the output from perl program 
     bufferedReader = new BufferedReader(new InputStreamReader(
       process.getInputStream())); 
     String line; 
     StringBuffer str = new StringBuffer(); 
     while ((line = bufferedReader.readLine()) != null) { 
      str.append(line); 
      System.out.println(line); 
     } 
     // process.waitFor(); 

     // Set the output on the textfield 
     // jTextArea1.setText(str.toString()); 

    } catch (Exception e) { 
     System.out.println("Exception: " + e.toString()); 
    } finally { 
     try { 
      bufferedReader.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

И мой Perl код

for (my $i=0; $i <= 9; $i++) { 
print "$i\n"; 
sleep(1); 
} 

Я могу получить выход программы на языке Perl в моей Java программы. Но я хочу, чтобы код perl предоставлял непрерывный вывод в Java-код. Подобно этому, когда цикл в perl печатает значение «i» в первый раз, я должен иметь возможность получить это значение в Java-коде. Чтобы я мог постоянно обновлять свой Java-интерфейс в соответствии с процессом, происходящим в коде Perl.

+0

Ваш дизайн несколько испорчен. Сейчас вы выполняете один процесс (perl) от другого. Поэтому, когда программа perl завершена, она возвращает ответ. Если вы хотите что-то «непрерывное», вам нужно будет написать несколько perl, чтобы поговорить с java, возможно, с именованным каналом или некоторым обычным хранилищем. – gideon

+0

@ Gideon: Да, это именно то, что я хочу, но у меня нет идеи, как это сделать. Можете ли вы поделиться некоторыми примерами, где эта вещь была реализована. – Chetna

+0

Конечно, это возможно. Единственное, что мешает вам это сделать, - это строка 'process.waitFor();' внутри вашего кода (который ждет, пока процесс не завершится). – Howard

ответ

3

Есть две части к этому:

  1. убедившись, что выход Perl не буферный поэтому выход сразу же доступен
  2. Making Java непрерывно читать из Perl.

Чтобы убедиться, что выход Perl не буферные вам нужно добавить следующую строку перед for:

STDOUT->autoflush(1);

Создания Java непрерывно чтения является немного более сложным и деталью подхода будет зависеть от того, что вы намерены делать с выходом.

Ниже приведен пример, где все, что требуется, - перенаправить выход дочернего процесса на выход Java.

Во-первых, класс, который расширяет резьбы требуется обрабатывать вывод порожденного процесса:

package com.example; 

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.io.OutputStream; 
import java.io.OutputStreamWriter; 

public class StreamRedirector extends Thread { 

    private InputStream inputStream; 
    private OutputStream outputStream; 

    public StreamRedirector(InputStream inputStream, OutputStream outputStream) { 
    this.inputStream = inputStream; 
    this.outputStream = outputStream; 
    } 

    public void run() { 
    OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream); 
    InputStreamReader inputStreamReader = new InputStreamReader(inputStream); 
    BufferedReader bufferedReader = new BufferedReader(inputStreamReader); 
    String line = null; 
    try { 
     while ((line = bufferedReader.readLine()) != null) { 
     outputStreamWriter.write(line + "\n"); 
     outputStreamWriter.flush(); 
     } 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
    } 
} 

Затем процесс может быть породил. В этом примере основной код немедленно ждет, когда процесс, который будет создан, будет завершен:

Runtime rt = Runtime.getRuntime(); 

Process proc; 
try { 
    proc = rt.exec(command); 
} catch (IOException e) { 
    throw new CustomException("Failed to execute.", e); 
} 

StreamRedirector outStreamRedirector = new StreamRedirector(proc.getInputStream(), System.out); 
StreamRedirector errStreamRedirector = new StreamRedirector(proc.getErrorStream(), System.err); 

outStreamRedirector.start(); 
errStreamRedirector.start(); 

int exitVal; 
try { 
    outStreamRedirector.join(); 
    errStreamRedirector.join(); 
    exitVal = proc.waitFor(); 
} catch (InterruptedException e) { 
    throw new CustomException("Failed to execute.", e); 
} 
+0

Большое спасибо. Теперь я вижу вывод на консоли java :-) – Chetna

+0

Но почему мы должны говорить perl, чтобы не буферизовать содержимое? Если вы выполняете один и тот же скрипт perl в оболочке, он отлично работает, выход сразу доступен. Почему это отличается при выполнении с Java? – ernesto

+0

BTW, у меня есть простой сценарий оболочки, который печатает что-то каждые 5 секунд, он отлично работает на оболочке и с Java, выход никогда не буферизуется, он сразу же доступен для другого конца, чтобы потреблять.Тем не менее, то же самое сделано в perl-скрипте, имеет разные эффекты. Скрипт perl отлично работает на оболочке, сразу же распечатывая вывод, но вывод буферизуется при выполнении из процесса Java. – ernesto

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