Runtime.getRuntime.exec(). Problemas na leitura da saída do processo

Boa noite,
é o seguinte, eu tenho que fazer um programa que executa um outro programa “A” escrito na linguagem C. Eu consegui interagir com o programa “A” através do metodo Runtime.getRuntime.exec ():

Process p = Runtime.getRuntime.exec (“A”);
InputStream input = p.getInputStream;
OutputStream output = p.getOutputStream;

No entanto, por mais que eu escreva no “output”, a saída do programa “A” só fica disponível no “input” quando eu escrevo no “output” o comando que encerra o programa “A”. Caso eu tente ler o “input” antes disso o meu programa fica eternamente esperando algo aparecer no “input”.

Alguém sabe como eu faço para que a cada escrita no “output” a saída gerada pelo programa “A” seja imediatamente armazenada no “input”.

Obrigado,
Elias

Ae cara, eu já tentei muito mexer com isso, e parece q naum tem nenhuma solução ideal.

Eu já pensei em colocar o outputstream e o inputstream em threads separadas, mas nunca implementei.
Eu sei q tem jeito, pq o Eclipse faz isso. Oq o Eclipse faz é lançar o programa usando o javaw, q naum abre terminal, e de alguma forma capturar esses 2 streams e colocar na janelinha dele. Vc pode ver q nem no Eclipse isso fica perfeito, se vc clica na janelinha com o mouse ela te joga pro topo to texto, e só qd vc digita alguma coisa q ela acha onde o texto devia ficar.

stdout e stdin é a coisa mais mal implementada em Java.

No meu caso, eu nem precisava passar nada pro stdin do programa C, só executar ele passando todos os dados por parâmetro e capturar o output. Acontece q o output sai tanto pelo stdout qt pelo stderr! Eu fiz de tudo pra tentar capturar os 2 e juntar tudo numa String só mas naum deu. A solução foi ler todo o stdout, depois ler todo o stderr, ficar com os 2 em 2 Strings separadas e procurar oq eu quisesse nas 2.

Se vc ou alguém descobrir alguma coisa sobre esse assunto posta aki!

cara,
para o teu problema a sun já lançou uma solução.

na versão 1.5, utize a classe ProcessBuilder. Ela funciona como a Runtime, mas tem algumas opções adiionais, entre elas redirecionar stderr para stdout (método redirectErrorStream(boolean b)).

                    String [] comando = {"comando"};
		ProcessBuilder processBuilder = new ProcessBuilder (comando);
		processBuilder.redirectErrorStream(true);
		p =  processBuilder.start();
		
		InputStream input = p.getInputStream();
		outputStream output = p.getOutputStream();

toda a a saída, inclusive o stderr estará disponível em “input”.

Quanto ao meu problema … eu tava olhando no Debug do eclipse e percebi que no processo retornado existe um atributo chamado “hasExited” e que a saída vai para o stdout exatamente no momento em q eu chamo o método para lê-lo. No entanto, isso soh acontece se o atributo “hasExited” é verdadeiro. A partir dai não consegui evoluir mais.

Olá,

Só para verificar uma coisa, Elias. Como é que você está lendo o stream em java? Com readLine()? E se for esse o caso, seu programa em C imprime uma quebra-linha? Porque se não, isso resultaria no método readLine() esperando para quebra-linha que nunca chega. Daí, o método só retorna quando o stream se feche (o que acontece justamente quando o programa C termina).

[]s,
Sami

Olá,

bom… no inicio eu realmente estava lendo com readLine. Mas eu jah havia desconfiado do problema e atualmente estou lendo com read(byte[]). E tb estou utilizando a classe ProcessBuilder.
Eu fiz um outro programa C o mais simples possível para teste (encerra quando o usuario digita “0”).

Outra coisa interessante é que eu testei com um programa escrito em haskell e deu algum “resultado”. Não sei bem como haskell funciona … só sei que tem um gerenciador de saida que escreve alguma coisa antes do que vai ser impresso. Por exemplo, em vez de escrever “olá” ele escreve “Prelude> olá”, onde esse “Prelude>” é o tal de gerenciador de saida que escreve. O interessante é que assim que eu escrevo alguma coisa na entrada do programa esse “Prelude>” vai imediatamente pra a saida e eu consigo lê-lo. No entanto o que realmenente interessa o “olá” soh vai pra a saída quando o programa encerra.

o meu código atualmente está assim:

            Process p;
	InputStream input;
	OutputStream output;
	
	
	try{
		String [] comando = {"./a.out"};
		ProcessBuilder processBuilder = new ProcessBuilder (comando);
		processBuilder.redirectErrorStream(true);
		p =  processBuilder.start();
		
		input = p.getInputStream();
		output = p.getOutputStream();
		
		
		byte b[] = new byte[600];
		String s;
		
		OutputStreamWriter outputWriter = new OutputStreamWriter(output);
		outputWriter.write("1\n");
		outputWriter.flush();
		
		outputWriter.write("0\n");
		outputWriter.flush();

		
		input.read(b);
		
		s = new String(b);
		System.out.println(s);
					
	}
	catch (Exception e) {
		// TODO: handle exception
		e.printStackTrace();
	}