2012-05-19 1 views
3

Мне нужно выполнить внешнее приложение, которое возвращает большие данные (требуется более 2 часов для завершения) nand, который непрерывно выводит данные.Выполнение внешней программы с помощью построителя процессов или apaw commons exec

Что мне нужно сделать, это выполнить эту программу асинхронно и захватить вывод в файле. Я пробовал использовать java process builder, однако он, кажется, зависает и возвращает выход только тогда, когда программа завершена или принудительно завершена.

Я попытался использовать построитель процессов и раздвинул новый поток, чтобы захватить вывод, но все равно это не помогло.

Затем я прочитал об apache commons exec и попробовал то же самое. Однако это также, кажется, занимает много времени и возвращает различные коды ошибок (для того же входа)

CommandLine cmdLine = new CommandLine("/opt/testsimulator"); 

    DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler(); 
    ByteArrayOutputStream stdout = new ByteArrayOutputStream(); 
    PumpStreamHandler psh = new PumpStreamHandler(stdout); 
    ExecuteWatchdog watchdog = new ExecuteWatchdog(60*1000); 
    Executor executor = new DefaultExecutor(); 
    executor.setStreamHandler(psh); 
    executor.setWatchdog(watchdog); 
    try { 
     executor.execute(cmdLine); 
    } catch (ExecuteException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

Любая помощь или рабочие примеры whould быть очень полезным

+0

Запускает программу из Java жесткое требование? Мне кажется, вы должны просто выполнить команду из оболочки и канала, которая будет выводиться в ваш целевой файл. – Perception

+0

Я сделал это с помощью ProcessBuilder, заботясь о том, чтобы обрабатывать входной поток и поток ошибок, и проблем не было. Возможно, у вас есть ошибка в вашей программе. –

+0

Не забудьте принять ответ ниже, если он вам поможет. – Gray

ответ

5

Ха. Использование ProcessBuilder должно работать для вашей конфигурации. Например, следующая схема работает для меня:

ProcessBuilder pb = new ProcessBuilder("/tmp/x"); 
Process process = pb.start(); 
final InputStream is = process.getInputStream(); 
// the background thread watches the output from the process 
new Thread(new Runnable() { 
    public void run() { 
     try { 
      BufferedReader reader = 
       new BufferedReader(new InputStreamReader(is)); 
      String line; 
      while ((line = reader.readLine()) != null) { 
       System.out.println(line); 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } finally { 
      is.close(); 
     } 
    } 
}).start(); 
// the outer thread waits for the process to finish 
process.waitFor(); 

Программа, которую я бегу это просто скрипт с целой кучей sleep 1 и echo линий:

#!/bin/sh 
sleep 1 
echo "Hello" 
sleep 1 
echo "Hello" 
... 

нить чтение из процесс выплескивает Hello каждую секунду или около того.

+0

Спасибо, была проблема с моим внешним приложением, и, следовательно, строитель процесса висел. Вышеприведенный код работает отлично. У меня был еще один вопрос. Я хочу выполнить программу асинхронно и сохранить файл в файле. Если я не использую process.waitFor(); программа завершится без сохранения результата. Есть ли способ достичь этого? – coder

+0

Вам не нужно записывать результат «Процесс». Если вы просто проигнорируете его, как только процесс завершится, он должен просто получить GC'd. В моем примере поток не помечен как демон. Если основная программа закончится, она будет ждать завершения потока. Если вы _don't_ хотите, чтобы он подождал, вы можете сделать thread = new Thread (...); thread.setDaemon (истина); thread.start(); 'pattern. – Gray