2017-01-24 9 views
3

Я использую ProcessBuilder для запуска команды. Выход команды находится в формате jSON, и я хочу вернуть String, а затем сопоставить его с моими моделями.ProcessBuilder не может вернуть JSon String

Проблема в том, что я не получаю результата при попытке прочитать поток из процесса. Команда, которую я использую, также имеет выходной сигнал не jSON. Если я использую эту команду версию, я получаю результат, так что проблема возникает только тогда, когда я хочу читать JSon ..

public String getPlate(String image) throws IOException, InterruptedException{ 
     ProcessBuilder pb = new ProcessBuilder("alpr", "-c eu", "-j on", "-n 1", image); 
     Process p = pb.start(); 
     p.waitFor(); 
     BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream())); 
     StringBuilder builder = new StringBuilder(); 
     String line; 
     while ((line = reader.readLine()) != null) { 
       builder.append(line); 
       builder.append(System.getProperty("line.separator")); 
      } 
      String result = builder.toString(); 
      return result; 
    } 

Используя эту команду, результат не дается, если я использую версию без JSon

ProcessBuilder pb = new ProcessBuilder("alpr", "-c eu", "-n 1", image); 

у меня есть результат ..

ответ

4

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

Ваш вывод, не являющийся JSON, вероятно, меньше, поэтому он не заполняет буферы в потоке процесса, что позволяет завершить процесс, а затем ваш родительский процесс Java может считывать данные в буферах труб.

Вы должны изменить порядок, что вы делаете:

public String getPlate(String image) throws IOException, InterruptedException{ 
     ProcessBuilder pb = 
      new ProcessBuilder("alpr", "-c eu", "-j on", "-n 1", image); 
     Process p = pb.start(); 

     BufferedReader reader = 
      new BufferedReader(new InputStreamReader(p.getInputStream())); 
     StringBuilder builder = new StringBuilder(); 
     String line; 
     while ((line = reader.readLine()) != null) { 
       builder.append(line); 
       builder.append(System.getProperty("line.separator")); 
     } 

     // wait for the child process *after* 
     // reading all its output 
     p.waitFor(); 

     String result = builder.toString(); 
     return result; 
} 

Это быстрое решение - это на самом деле не очень надежен. Если ваш дочерний процесс также генерирует значительный вывод ошибки, который также может блокироваться.

При необходимости можно использовать методы redirectError(), redirectInput(), and redirectOutput(), чтобы предотвратить такую ​​блокировку.