# Java Subprozess, StdIn und StdOut benutzen



## Patrick_G (20. Jul 2006)

Hallo,

(vorsicht, Anfängerfrage!)

ich möchte aus einem Javaprogramm (J) ein interaktives Programm (P) starten, und über die Kommandozeile fernsteuern. D.h. ich möchte die Eingaben, die von der Tastatur in J eingegeben werden nach P weiterreichen und die Ausgabe von P auf StdOut von J ausgeben. Dabei ist nicht klar, wie lange P läuft und welche Eingaben es wann bekommt. 

Starten des Programms P ist kein Problem (ich benutze ProcessBuilder(args).start()). Wie sollte ich nun vorgehen, diese Umleitungen herzustellen?  Muss ich die Ein-/Ausgaben per Hand lesen und schreiben (mit read() oder readLine()) oder kann ich die Umleitungen direkt setzen?

Gruß,

Patrick


----------



## Kola (20. Jul 2006)

Aus der API von java.lang.Process:



> All its standard io (i.e. stdin, stdout, stderr) operations will be redirected to the parent process through three streams (getOutputStream(), getInputStream(), getErrorStream()). The parent process uses these streams to feed input to and get output from the subprocess



In J startest du über ProcessBuilder.start() den Process, dann holst du dir von J aus den Input- und Outputstream von P. Diese Streams sind dann deine Umleitungen.


----------



## Patrick_G (20. Jul 2006)

Kola hat gesagt.:
			
		

> Aus der API von java.lang.Process:
> 
> 
> In J startest du über ProcessBuilder.start() den Process, dann holst du dir von J aus den Input- und Outputstream von P. Diese Streams sind dann deine Umleitungen.



Danke, ich werde das mal versuchen und mich wieder melden.

Patrick


----------



## Corran (25. Sep 2007)

ah gut das hier trift so in etwa mein problem, hab naemlich was aenliches vor. ich hab es genauso gemacht wie der kollege vor mir, allerdings hab ich das problem, das die sache mit dem stdin nicht so recht will. hier waere das problematische codesegment, allerdings nur vereinfacht nachempfunden, geht ja nur um das prinzipielle problem.

code:

import java.io.*;

public class Test
{
	public static void main(String[] sArgs) throws Exception
	{
		Process process = (Runtime.getRuntime()).exec("xterm");	//linux
//		Process process = (Runtime.getRuntime()).exec("cmd");	//windows

		BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
		PrintStream printer = new PrintStream(process.getOutputStream());

		String str = "ping web.de";	//linux
//		String str = "ping web.de -t"; //windows

		printer.println(str);

		while(true)
		{
			str = reader.readLine();
			System.out.println(str);
		}
	}
}

so und das muesste eigentlich (sofern ich das aus der api alles rchtig verstanden hab) auf der console die ausgabe vom ping befehl geben.
leider klapts aber nicht, da nach meinem wissensstand ind dieser zeile: "printer.println(str);" der befehl nicht and die stdin des prozesses weiter gegeben wird. waarum? keine ahnung ^_^'
ich habs auch mit anderen classen als dem PrintStream versucht, nix hat bisher geklapt. bis etwas rat los und fuer jeden hinweis dankbar.

thx @ all


----------



## Murray (25. Sep 2007)

Probier mal printer.flush(); nach dem println.

Das Beispiel mit ping ist jetzt wirklich nur ein vereinfachtes Beispiel, oder? Ansonsten könntest du ping ja auch direkt ausführen (ohne Umweg über den Shell-Prozess).


----------



## Corran (25. Sep 2007)

das printer.flush(); hat leider nix gebracht, trotzdem danke Murray.
ja das is wirklich nurn vereinfachtes beispiel ^_^
aber prinzipiel muesste doch das alles so laufen oder?


----------



## Murray (25. Sep 2007)

Vermutlich verhindert das blockierende Lesen des Input-Streams, dass die Ausgabe korrekt verarbeitet werden kann. Lagert man das Lesen in einen Thread aus, sollte es klappen (zumindest funktioniert es so bei mir unter Windows)


```
import java.io.*;

public class Ping {
	public static void main(String[] sArgs) throws Exception {
		//Process process = (Runtime.getRuntime()).exec("xterm"); //linux
		Process process = (Runtime.getRuntime()).exec("cmd"); //windows

		final BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
		PrintStream printer = new PrintStream(process.getOutputStream());

		//String str = "ping web.de"; //linux
		String str = "ping web.de -t"; //windows

		printer.println(str);
		printer.flush();


		new Thread( new Runnable() {

			public void run() {
				while(true) {
					try {
						String str = reader.readLine();
						System.out.println(str);
					} catch ( IOException iox) {
						iox.printStackTrace();
					}
				}
			}
		}).start();
	}
}
```

<off-topic>
Mit den code-Tags ist Source-Code besser lesbar.
</off-topic>


----------



## Corran (25. Sep 2007)

also unter linux klapts immer noch nicht, ich boot ma windows und schau da ma.
sollte mich aber wundern das es daran liegt, im ursprungsprog lauffen ein und ausgabe in unterschiedlichen threads und da lass ich das eingegebene nach der uebergabe an den subprozes auch noch ma ausgeben, was er auch jedes mal tut, also er bleibt nicht bei der uebergabe an den subprozes stehn, fuer ihn klapt das alles, wird nur nicht richtig ausgefueht.


----------



## Corran (25. Sep 2007)

ok unter windwos lauft alles, da lief sogar mein programm nach der hunzufuegung des printer.flush(); an der von dir beschriebenen stelle.
leider nutzt mir das programm unter windows nichts, da ich es fuer linux brauche, aber jetzt is wenigstens ein ansatz da und die gewissheit das meine ueberlegungen grundsaetzlich richtig waren (wollte mich schon fuer beklopt erklaeren lassen)


----------



## Murray (26. Sep 2007)

Vielleicht ist das für dich interessant (besonders der letzte Post).


----------



## Corran (27. Sep 2007)

ja besten dank, daswars, die xterm stellt das problem dar, ich hab sie durch die bash ersetzt und das mit dem printer.flush() noch hinzu genommen und zag lief es, viel dank.
so nun zum grossen programm, aendern und auf laufzeit probleme warten xD

danke noch mal


----------

