2012-05-15 4 views
2

Мне нужно извлечь входной поток процесса после его запуска. Сегодня я могу получить исходную информацию, но метод не возвращается, пока я не закрою приложение (в этом случае приложение запускается процессом: gedit и firefox). Я имею в виду, я знаю, что он просто вернется после закрытия процесса, но я хотел бы получить обходное решение, чтобы получить это до закрытия процесса. Смотрите мой код ниже.Как извлечь входной поток до завершения процесса

public class ProcessInvokerExtractingProcessInformation { 

    public static void main(String args[]) { 



     try { 
      Process pOpenApp = new ProcessBuilder(new String[] { "gedit", 
        "/home/thais/Documents/gedit_doc1" }).start(); 

      printInformation("pOpenApp", pOpenApp); 

      // * just for testing error message and input stream 
      Process openFirefox = new ProcessBuilder(new String[] { "firefox" }) 
        .start(); 
      printInformation("lsInstruction", openFirefox); 


      deleteProcess(pOpenApp); 
      deleteProcess(openFirefox); 

     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 




    // method for testing information we can see regarding the process 
    public static void printInformation(String id, final Process process) { 

     System.out.println(" Process " + id + ":"); 

        //tried to run in a separated thread but didn't work as well 
      Runnable r = new Runnable(){ 
      public void run(){ 
       System.out.print("\n  Process error message -> "); 
      printScannedStream(process.getErrorStream()); 
      System.out.println("\n  Process input message -> "); 
      printScannedStream(process.getInputStream()); 
      } 

      }; 

      Thread a = new Thread(r); 
      a.start(); 



      /* other approaches to print the streams, tried before 
       StringWriter writer = new StringWriter(); 

      try { 
       PrintWriter pWriter = new PrintWriter(new 
       BufferedOutputStream(process.getOutputStream())); 
       pWriter.write("Hi"); pWriter.flush(); System.out.println(
       " Process output stream is for writing so there is no information " 
      ); 
      *//* 
      InputStreamReader isr = new InputStreamReader(
        process.getErrorStream()); 
      BufferedReader br = new BufferedReader(isr); 
      System.out.print("\n  Process error message -> "); 
      while (br.readLine() != null) { 
       System.out.print(br.readLine()); 
      } 
      System.out.println("\n  Process input message -> "); 

      isr = new InputStreamReader(process.getInputStream()); 
      br = new BufferedReader(isr); 
      while (br.readLine() != null) { 
       System.out.print(br.readLine()); 
      } 

      br.close(); 
      isr.close();*/ 
      /* 
      * IOUtils.copy(process.getErrorStream(), writer, null); 
      * System.out.println("  Process error message -> " + 
      * writer.toString()); 
      * 
      * IOUtils.copy(process.getInputStream(), writer, null); 
      * System.out.println("  Process input stream message -> " + 
      * writer.toString()+"\n"); 

     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
*/ 
    } 

    /** 
    * Method that close all streams and after destroy the process It's 
    * important to close the streams to avoid file descriptions leaking 
    * 
    * @param process 
    */ 
    public static void deleteProcess(Process process) { 
     try { 
      process.getInputStream().close(); 
      process.getOutputStream().close(); 
      process.getErrorStream().close(); 
      process.destroy(); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 



    public static void printScannedStream(java.io.InputStream is) { 
     try { 
      Scanner scanner = new Scanner(is); 
      while(scanner.hasNext()) { 
       System.out.print(scanner.next()); 

      } 

     } catch (java.util.NoSuchElementException e) { 
      e.printStackTrace(); 
     } 


    } 

} 

ответ

0

У меня была такая же проблема, и я решил ее использовать с помощью дополнительной нити.

class InputHandler implements Runnable { 

    InputStream input_; 

    InputHandler(InputStream input) { 
     input_ = input; 
    } 

    public void run() { 
     try { 
      int c; 
      String line = ""; 
      while ((c = input_.read()) != -1) { 
      if (((char) c == '\r') || ((char) c == '\n')) { 
      if (!line.isEmpty()) flushString(line); 
      line = ""; 
      } else 
      line += (char) c; 
      } 
     } catch (Throwable t) { 
      t.printStackTrace(); 
     } 
    } 

    private void flushString(String s) { 
    // any code to process data from stream 
    Logger.debug("library: " + getClass().getName() + ": compress: output: " + s); 
    } 

} 




Process process = run.exec(ffmpegCmdString); 
// read output 
InputHandler stderrHandler = new InputHandler(process.getErrorStream()); 
new Thread(stderrHandler).start(); 
InputHandler stdoutHandler = new InputHandler(process.getInputStream()); 
new Thread(stdoutHandler).start(); 
process.waitFor(); 
+0

Привет, Николай, большое вам спасибо. Я пробовал ваш код, но на самом деле он работал как мой. Я имею в виду, что он печатает информацию о процессе до закрытия процесса, но программа все еще ждет завершения процесса для продолжения. Я хотел что-то, что не остановило бы приложение. Я имею в виду, он печатал бы, если бы что-то печаталось и после этого продолжал приложение регулярно. Считаете ли вы, что это возможно? –

+0

Привет, Николай, на самом деле теперь ваш код работает идеально для меня. Мне просто пришлось удалить waitFor(), так как я использую этот метод для нескольких процессов. –

+0

А также, сравнивая с моим кодом, я заметил, что логика была схожа. Моя ошибка заключалась в том, что я пытался увидеть errorStream и inputStream в том же запущенном потоке. Создание двух потоков, по одному для каждого потока, решило проблему. Еще раз большое спасибо! –

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