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