2012-10-22 38 views
10

Bir dosyanın Revizyon numarasını döndüren bir komut yürütüyorum; 'dosya adı'. Ancak, komutun çalıştırılmasında bir sorun varsa, uygulama kilitlenir. Bu durumdan kaçınmak için ne yapabilirim? Lütfen kodumu aşağıda bulabilirsiniz.Runtime.getRuntime(). Exec (cmd) asılı

String cmd= "cmd /C si viewhistory --fields=revision --project="+fileName; 
Process p = Runtime.getRuntime().exec(cmd) ; 
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream())); 
String line = null; 
while ((line = in.readLine()) != null) { 
System.out.println(line); 
} 

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

[ProcessBuilder] 'a bir göz atın (http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html). Bu tür bir şey yapmak için daha basit bir API budur – RNJ

+0

Çıkış yoksa, "readLine" sonsuza dek engeller. – assylias

+0

@assylias: Çıktının olup olmadığını nasıl kontrol edebilirim? – user1688404

cevap

24

Sorun şu ki, yalnızca InputStream okuyorsunuz ve ErrorStream okumadığınız içindir. Ayrıca, her iki akışın da paralel olarak okunmasına dikkat etmelisiniz. Halihazırda çıktı akışından aktarılan verilerin işletim sistemi tamponunu doldurması, okuyucunuzun arabelleği boşaltma şansı vermesi için otomatik olarak askıya alınacaktır. Ama program hala çıktıların işlenmesini bekliyor olacak. Bu nedenle asılma gerçekleşir. Bu kod dayanmaktadır

String cmd= "cmd /C si viewhistory --fields=revision --project="+fileName; 
Process p = Runtime.getRuntime().exec(cmd) ; 
s1 = new ReadStream("stdin", p.getInputStream()); 
s2 = new ReadStream("stderr", p.getErrorStream()); 
s1.start(); 
s2.start(); 
p.waitFor();   
} catch (Exception e) { 
e.printStackTrace(); 
} finally { 
    if(p != null) 
     p.destroy(); 
} 
+0

Bu en azından benim için mükemmel! teşekkürler –

+1

Bu kod bloğu beni de cahil hehe olmaktan korusun :) – Akyo

+0

Son derece yararlı teşekkür ederim! – welterw8

3

aşağıdaki gibi giriş ve Hata Akış hem işlemek için ayrı bir sınıf oluşturabilir

,

public class ReadStream implements Runnable { 
    String name; 
    InputStream is; 
    Thread thread;  
    public ReadStream(String name, InputStream is) { 
     this.name = name; 
     this.is = is; 
    }  
    public void start() { 
     thread = new Thread (this); 
     thread.start(); 
    }  
    public void run() { 
     try { 
      InputStreamReader isr = new InputStreamReader (is); 
      BufferedReader br = new BufferedReader (isr); 
      while (true) { 
       String s = br.readLine(); 
       if (s == null) break; 
       System.out.println ("[" + name + "] " + s); 
      } 
      is.close();  
     } catch (Exception ex) { 
      System.out.println ("Problem reading stream " + name + "... :" + ex); 
      ex.printStackTrace(); 
     } 
    } 
} 

aşağıdaki gibi öyle kullanmak yolu, Aynı fikir Arham'ın cevabı, ama bir java 8 paralel akışı kullanılarak uygulanır, bu biraz daha özlü yapar.

public static String getOutputFromProgram(String program) throws IOException { 
    Process proc = Runtime.getRuntime().exec(program); 
    return Stream.of(proc.getErrorStream(), proc.getInputStream()).parallel().map((InputStream isForOutput) -> { 
     StringBuilder output = new StringBuilder(); 
     try (BufferedReader br = new BufferedReader(new InputStreamReader(isForOutput))) { 
      String line; 
      while ((line = br.readLine()) != null) { 
       output.append(line); 
       output.append("\n"); 
      } 
     } catch (IOException e) { 
      throw new RuntimeException(e); 
     } 
     return output; 
    }).collect(Collectors.joining()); 
} 

Sen program kilitleniyor aradığınız eğer girdi gerektiriyorsa bu yöntem gerçekleşecek olan askıda olacağı bu

getOutputFromProgram("cmd /C si viewhistory --fields=revision --project="+fileName); 

Not gibi yöntemini çağırabilirsiniz.

+0

Çalışıyor harika çalışıyor 'mvn doğrulamak' ve' cmd/C' ile sarmalamıyorum - ikinci bir kabuğun sarılmasının yararı nedir biliyor musunuz? –

+1

OP'nin komut dizesini tam olarak kopyaladım ve "cmd/C" ile başladım. Bu durumda sarmanın bir yararı olduğunu sanmıyorum. – mikeyreilly