2015-03-03 4 views
1

Я вызываю p = Runtime.getRuntime(). Exec (command) на Java 1.8. Команда вызывает Баш скрипт следующим образом:Java getRuntime Exec

#!/bin/bash 
args=("[email protected]") 
cat /home/user/Downloads/bigtext.txt | grep ${args[0]} 

выше Баш скрипт отлично работает, когда вызывается с помощью командной строки. Когда вызывается в моем приложении Java с помощью exec(), я не получаю вывод CAT. он, кажется, не прошел мимо p.waitFor(); Где я иду не так?

Если я запускаю команду напрямую, например, «ls -alF», все работает так, как ожидалось.

$ java -version java version "1.8.0_31" Java(TM) SE Runtime Environment (build 1.8.0_31-b13) Java HotSpot(TM) 64-Bit Server VM (build 25.31-b07, mixed mode) 


String tmp = "/home/user/search "+input;   
System.out.println(tmp); // /home/user/search sometextarg 
String woa = executeCommand(tmp); 


private String executeCommand(String command) {  
     StringBuilder output = new StringBuilder(); 
       BufferedReader reader = null; 
     Process p; 
     try { 
      p = Runtime.getRuntime().exec(command); 
      p.waitFor(); 

         reader = new BufferedReader(new InputStreamReader(p.getInputStream())); 

      String line = ""; 

      while ((line = reader.readLine())!= null) { 
       output.append(line + "\n"); 
      } 

     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

     return output.toString(); 
    } 
+0

Насколько велик 'bigtext.txt'? Для чего вы хотите? –

+0

его текстовый файл 136 Мб – DevilCode

ответ

3

Ваш процесс Java и сценарий в тупик ждут друг от друга: вы ждете, чтобы процесс выхода, процесс ждет вас, чтобы читать вывод.

Это работает для ls -alF и других команд с малыми выходами, потому что они все вписываются в буфер трубы (64kib в моей системе).

Просто переместите p.waitFor() ниже время цикла, и вы будете иметь больше удачи:

private String executeCommand(String command) {  
    StringBuilder output = new StringBuilder(); 
      BufferedReader reader = null; 
    Process p; 
    try { 
     p = Runtime.getRuntime().exec(command); 
     reader = new BufferedReader(new InputStreamReader(p.getInputStream())); 

     String line = ""; 
     while ((line = reader.readLine())!= null) { 
      output.append(line + "\n"); 
     } 
     p.waitFor(); 

    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    return output.toString(); 
} 

Если вы дополнительно хотите, чтобы это правильно работать с значения, содержащие пробелы и некоторые другие символы, вы должны:

  1. "${args[0]}" в вашем скрипте.
  2. Перепишите executeCommand, чтобы использовать Runtime.exec(String[]) вместо Runtime.exec(String).
+0

_в вас ждет, чтобы вы прочитали вывод. Можете ли вы это объяснить? –

+1

@SotiriosDelimanolis Ваш скрипт может записывать данные намного быстрее, чем ваша программа Java может его прочитать. Однако это не будет [вызвать беспорядок] (https://www.youtube.com/watch?v=HnbNcQlzV-4), потому что вместо того, чтобы как можно быстрее передавать данные, полностью подавляя программу Java, сценарий будет 1 напишите кусок данных, 2. дождитесь, пока он будет прочитан. 3. повторите по мере необходимости (так работают трубы). В вашем случае сценарий застрял на шаге 2, потому что вы вообще не читали трубку и вместо этого ждали выхода программы. –

+0

Часть, которую я хотел бы вам уточнить, - это то, как работают трубы. Неиспользуемый процесс не должен ждать, пока Java (или любой другой процесс) не прочитает его стандартную версию. –