2008-09-13 24 views
28

Java'nın ProcessBuilder sınıfı aracılığıyla bir işlem başlatırsam, bu işlemin standart, standart çıkış ve standart hata akışları için Java InputStreams ve OutputStreams olarak tam erişimim vardır. Ancak, bu akışları System.in, System.out ve System.err'a sorunsuz bir şekilde bağlamanın bir yolunu bulamıyorum.Java'da devralınan stdin/stdout/stderr ile bir işlem başlatma 6

Tek bir InputStream numaralı altprogramın standart dışı ve standart hatalarını içeren tek bir numaralı bağlantıyı kullanmak ve yalnızca bunun üzerinden dönüp standart çıkışım yoluyla göndermek mümkündür - ancak bunu yapmanın bir yolunu bulamıyorum. Kullanıcı, C system() numaralı çağrıyı kullanmış olsaydı, sürece girebilir.

Bu, çıktığında Java SE 7'de mümkün görünüyor — Sadece bir çözüm olup olmadığını merak ediyorum. Çocuğun işleminde isatty() sonucu, yeniden yönlendirme ile gerçekleşirse bonus puanları.

+0

Üzgünüz, yardımcı olamam. – jjnguy

+0

Sorun değil. (Bu arada seni reddeden ben değildim.) –

+0

Heh, bana karşı oy kullanmayan adam sayesinde. Ve teşekkür ederim, John beni reddetmediği için. – jjnguy

cevap

15

Process çıkış, hata ve giriş akışlarını Sistem sürümlerine kopyalamanız gerekir. Bunu yapmanın en kolay yolu, Commons IO paketinden IOUtils sınıfını kullanmaktır. copy method, ihtiyacınız olan şey gibi görünüyor. Kopyalama yöntemi çağırmalarının ayrı iş parçacıklarında olması gerekir. İşte

temel kodudur:

// Assume you already have a processBuilder all configured and ready to go 
final Process process = processBuilder.start(); 
new Thread(new Runnable() {public void run() { 
    IOUtils.copy(process.getOutputStream(), System.out); 
} }).start(); 
new Thread(new Runnable() {public void run() { 
    IOUtils.copy(process.getErrorStream(), System.err); 
} }).start(); 
new Thread(new Runnable() {public void run() { 
    IOUtils.copy(System.in, process.getInputStream()); 
} }).start(); 
+4

Tam olarak değil. IOUtils.copy, InputStream'i ilk argüman olarak alır, bu nedenle getOutputStream ile çalışmaz. Yani IOUtils.copy (process.getInputStream(), System.out); GetOutputStream aslında sürecin girişine pipet verdiği için biraz kafa karıştırıcı. – Eelco

+0

Bunun yapısı doğru görünüyor, ancak IOUtils parametrelerinin geri bildirimler gibi göründüğüne de katılıyorum. process.getInputStream(), stdout'a aktarılacak olan şeydir (evet, geriye doğru geliyor). Yani bu yapı iyi görünüyor, IOUtils çağrıları yanlış görünüyor ve şimdi bana biraz karıştı ... – titania424

+1

Yanlış. Bu sadece ** boruları ebeveynlerin ve çocuğun giriş/çıkış akımları arasındaki veri **, ** onları miras almasına izin vermez. Örneğin, Java komutu bir terminalde (C isatty() == true veya System.console()! = Null) başlatılmış olsa bile, çocuk kendisini terminalde çalıştırıldığını görmez, çünkü giriş/çıkış akışları borular. Bu önemlidir çünkü bazı (çoğu) programlar terminalde çalıştırıldığında farklı davranırlar. Java 7'nin ProcessBuilder.Redirect.INHERIT bu konuda doğru bir şekilde çalışır. – Tobia

13

derler ve Commons IO kullanımı gerektirmez John'un cevabı bir varyasyonu: System.in için

private static void pipeOutput(Process process) { 
    pipe(process.getErrorStream(), System.err); 
    pipe(process.getInputStream(), System.out); 
} 

private static void pipe(final InputStream src, final PrintStream dest) { 
    new Thread(new Runnable() { 
     public void run() { 
      try { 
       byte[] buffer = new byte[1024]; 
       for (int n = 0; n != -1; n = src.read(buffer)) { 
        dest.write(buffer, 0, n); 
       } 
      } catch (IOException e) { // just exit 
      } 
     } 
    }).start(); 
} 
+0

System.in sorusunu yanıtlamıyor. – solotim

+0

Neden boru (System.in, process.getOutputStream()); işe yaramaz mı? –

3

yerine pipein() aşağıdaki kullanmak pipe()

pipein(System.in, p.getOutputStream()); 

Uygulama:

private static void pipein(final InputStream src, final OutputStream dest) { 

    new Thread(new Runnable() { 
     public void run() { 
      try { 
       int ret = -1; 
       while ((ret = System.in.read()) != -1) { 
        dest.write(ret); 
        dest.flush(); 
       } 
      } catch (IOException e) { // just exit 
      } 
     } 
    }).start(); 

} 
+0

Bu işe yaramaz. –