2012-10-22 13 views
10

मैं एक आदेश निष्पादित कर रहा हूं जो मुझे फ़ाइल की संशोधन संख्या देता है; 'फ़ाइल का नाम'। लेकिन अगर आदेश को निष्पादित करने में कुछ समस्या है, तो एप्लिकेशन लटकता है। उस स्थिति से बचने के लिए मैं क्या कर सकता हूं? कृपया मेरे कोड के नीचे पाएं।Runtime.getRuntime()। Exec (cmd) hanging

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] (http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html) पर एक नज़र डालें। यह इस तरह की चीज करने के लिए एक आसान एपीआई है – RNJ

+0

यदि कोई आउटपुट नहीं है, तो 'readLine' हमेशा के लिए अवरुद्ध होगा। – assylias

+0

@assylias: कोई आउटपुट नहीं है तो मैं कैसे जांचूं? – user1688404

उत्तर

24

मुझे लगता है कि समस्या यह है कि आप केवल इनपुटस्ट्रीम पढ़ रहे हैं और त्रुटि स्ट्रीम पढ़ रहे हैं। आपको यह भी ध्यान रखना होगा कि दोनों धाराएं समानांतर में पढ़ी जाती हैं। ऐसा हो सकता है कि वर्तमान में आउटपुट स्ट्रीम से पाइप डेटा ओएस बफर भरता है, आपके पाठक को बफर खाली करने का मौका देने के लिए आपके exec कमांड को स्वचालित रूप से निलंबित कर दिया जाएगा। लेकिन कार्यक्रम अभी भी आउटपुट की प्रक्रिया के लिए इंतजार कर रहा है। इसलिए, लटका होता है।

आप एक अलग वर्ग के रूप में निम्नानुसार दोनों इनपुट और त्रुटि स्ट्रीम को संभालने के लिए बना सकते हैं,

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

जिस तरह से आप यह इस प्रकार है का उपयोग करें,

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

यह मेरे लिए कम से कम सही है! धन्यवाद –

+1

हाँ कि कोड का ब्लॉक मुझे अज्ञानी होने से भी बचाता है :) – Akyo

+0

बेहद सहायक धन्यवाद! – welterw8

3

इस कोड पर आधारित है अरहम का एक ही विचार, लेकिन जावा 8 समांतर धारा का उपयोग करके कार्यान्वित किया गया है, जो इसे थोड़ा और संक्षिप्त बनाता है।

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

आप की तरह इस

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

नोट है कि इस विधि अगर कार्यक्रम आप रुक जाता है बुला रहे हैं अगर यह इनपुट की आवश्यकता है रखती है, जो होगा विधि कॉल कर सकते हैं।

+0

महान चल रहा है 'एमवीएन सत्यापित' काम करता है और मैं इसे 'cmd/c' से लपेट नहीं रहा हूं - क्या आपको पता है कि दूसरा खोल लपेटने का क्या फायदा है? –

+1

मैंने ओपी की कमांड स्ट्रिंग को बिल्कुल कॉपी किया और यह "cmd/c" से शुरू हुआ। मुझे नहीं लगता कि इस मामले में इसे लपेटने का कोई फायदा है। – mikeyreilly

संबंधित मुद्दे