2012-10-22 49 views
10

Tôi đang thực hiện một lệnh trả về cho tôi số sửa đổi của một tệp; 'tên tệp'. Nhưng nếu có một số vấn đề thực thi lệnh, thì ứng dụng sẽ treo lên. Tôi có thể làm gì để tránh tình trạng đó? Vui lòng tìm bên dưới mã của tôi.Runtime.getRuntime(). Exec (cmd) treo

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

Hãy xem [ProcessBuilder] (http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html). Đây là một API đơn giản hơn để thực hiện loại điều này – RNJ

+0

Nếu không có đầu ra, 'readLine' sẽ chặn mãi mãi. – assylias

+0

@assylias: làm thế nào để tôi kiểm tra nếu không có đầu ra? – user1688404

Trả lời

24

Tôi đoán vấn đề là bạn chỉ đọc InputStream và không đọc ErrorStream. Bạn cũng phải cẩn thận rằng cả hai luồng được đọc song song. Nó có thể xảy ra như vậy hiện tại các dữ liệu đường ống từ dòng đầu ra đầy lên bộ đệm hệ điều hành, lệnh exec của bạn sẽ được tự động bị đình chỉ để cung cấp cho người đọc của bạn một cơ hội để làm trống bộ đệm. Nhưng chương trình vẫn sẽ chờ đợi cho đầu ra để xử lý. Do đó, hang xảy ra.

Bạn có thể tạo ra một lớp riêng biệt để xử lý cả đầu vào và Lỗi Suối như sau,

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(); 
     } 
    } 
} 

Cách bạn sử dụng nó như sau,

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

điều này hoàn hảo ít nhất đối với tôi! cảm ơn –

+1

Yep rằng khối mã cũng tiết kiệm cho tôi khỏi bị vô minh hehe :) – Akyo

+0

Vô cùng hữu ích cảm ơn bạn! – welterw8

3

Mã này được dựa trên cùng một ý tưởng câu trả lời của Arham, nhưng được thực hiện bằng cách sử dụng một luồng song song java 8, làm cho nó ngắn gọn hơn một chút.

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()); 
} 

Bạn có thể gọi phương thức như thế này

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

Lưu ý rằng phương pháp này sẽ treo nếu chương trình bạn đang gọi bị treo, mà sẽ xảy ra nếu nó đòi hỏi đầu vào.

+0

Hoạt động tuyệt vời chạy 'mvn verify' và tôi không gói nó với' cmd/C' - bạn có biết lợi ích của việc gói một shell thứ hai là gì không? –

+1

Tôi đã sao chép chính xác chuỗi lệnh của OP và bắt đầu bằng "cmd/C". Tôi không nghĩ có lợi ích gì khi gói nó trong trường hợp này. – mikeyreilly

Các vấn đề liên quan