ProcessBuilder

Olá pessoal.
Estou com um problema gostaria de saber se alguém pode me ajudar com alguma solução. Eu preciso chamar um programa dentro do meu programa, para isso posso usar o ProcessBuilder, porém eu gostaria que as saídas (impressão de terminal) desse programa chamado fossem impressas no mesmo terminal que o programa pai chamou o processo ou então abrir um terminal novo que mostrasse as saídas do novo processo.

Alguma dica?
Obrigado

Não tem outra saída. Você precisa criar uma thread que fique lendo o OuputStream e o ErrorStream do Process criado pelo ProcessBuilder, e imprima tudo que vier por ali no System.out.

Para facilitar, você pode definir como true a propriedade redirectErrorStreamtToOutputStream do Process.

Oi Lucas,

Executar processos externos a JVM pode ser traiçoeiro, pois se você não consumir todos os streams de saída do processo, o processo pode “congelar” sua aplicação.
Recomendo a leitura desse artigo aqui: When Runtime.exec() won’t

Nele o autor descreve a criação de uma classe (StreamGobbler) que faz exatamente o que o Vini acabou de falar.
Boa leitura.

[]´s

vc poderia me passar um exemplo de como eu poderia ficar lendo, pois a unica maneira que eu consegui fazer essas leitura foi apenas quando o precesso criado termina, ai eu consigo imprimir todas as saídas que foram geradas, mas eu preciso mostrar essas saídas em tempo real como vc disse algo que fique lendo as saídas.

Você leu o artigo que passei no post anterior? Tem um link, dá uma olhada.
Lá tem tudo isso, mas precisa ler para entender.

[]´s

Posso sim: When Runtime.exec() won’t

O artigo é muito bom, realmente mostra como lidar bem com chamadas de outros processos, mas eu eu ainda não consigo imprimir as minhas saidas do programa chamado em tempo real, parece que a BufferedReader bloqueia até que o programa termine e complete suas saídas! Eu posso ter entendido errado os exemplos mas eu rodando e eles e tal, mas não estou conseguindo superar esse problema.
Se alguém tiver mais alguma idéia para ajudar. Obrigado.

[quote=lucasmb87]O artigo é muito bom, realmente mostra como lidar bem com chamadas de outros processos, mas eu eu ainda não consigo imprimir as minhas saidas do programa chamado em tempo real, parece que a BufferedReader bloqueia até que o programa termine e complete suas saídas! Eu posso ter entendido errado os exemplos mas eu rodando e eles e tal, mas não estou conseguindo superar esse problema.
Se alguém tiver mais alguma idéia para ajudar. Obrigado.[/quote]

Você usou o StreamGobbler que ele cita na última página do artigo? Não tem erro, é copiar, colar no seu projeto, usa-lo e pronto!

o método readLine() da BufferedReader parece bloquear, pois eu coloco um System.out para imprimir imediatamente ante e depois desse método e o segundo print so é mostrado depois que todo o programa chamado termina.

Sim, por isso o StreamGobbler é disparado com start().
Ele cria uma segunda thread.

Eu fiz um programa simples para testar, ele imprime de 1 a 10 entre cada impressão de numero ele da um sleep pequeno, o que acontece é que o classe que copiei do arquito so impreme no terminal depois o programa inteiro terminou, ou seja ele fica esperando alguns segundos ate que imprime de uma vez só 1 2 3 4 5 6 7 8 9 10.
Eu realmente preciso de alguma solução para imprimir em tempo real cada saida do program chamado!

[quote=lucasmb87]Eu fiz um programa simples para testar, ele imprime de 1 a 10 entre cada impressão de numero ele da um sleep pequeno, o que acontece é que o classe que copiei do arquito so impreme no terminal depois o programa inteiro terminou, ou seja ele fica esperando alguns segundos ate que imprime de uma vez só 1 2 3 4 5 6 7 8 9 10.
Eu realmente preciso de alguma solução para imprimir em tempo real cada saida do program chamado![/quote]
Você leu mesmo o artigo??? Vc está insistindo no mesmo problema e estamos insistindo na mesma solução! Se vc ainda está insistindo no problema é pq NÃO leu o artigo.
:shock: :shock: :shock:

Sim eu li e estou usando exatamente como foi dito no artigo, o que estou tentando explicar é que não soluciona meu problema, mas o metodo readLine() bloqueia a thread que faz a impressão das saidas até que o processo termine por completo

[code]
public class StreamGobbler extends Thread{

InputStream is;
String type;

StreamGobbler(InputStream is, String type)
{
    this.is = is;
    this.type = type;
}
public void run()
{
    try
    {
        InputStreamReader isr = new InputStreamReader(is);
        BufferedReader br = new BufferedReader(isr);
        String line=null;
        //aqui o readLine bloqueia a thread
        while ( (line = br.readLine()) != null){
            System.out.println(type + ">" + line);
        }
        
        } catch (IOException ioe)
          {
            ioe.printStackTrace();
          }
}

}
public class GoodWindowsExec {

    public static void main(String args[])
{
    try
    {
        Runtime rt = Runtime.getRuntime();
        Process proc = rt.exec( "/home/lbitt/Desktop/sleepLoop");

        // any error message?
        StreamGobbler errorGobbler = new
            StreamGobbler(proc.getErrorStream(), "ERR");

        // any output?
        StreamGobbler outputGobbler = new
            StreamGobbler(proc.getInputStream(), "OUT");

        // kick them off
        errorGobbler.start();
        outputGobbler.start();

        // any error???
        
        //proc.waitFor();
        System.out.println("Main thread....");
    } catch (Throwable t)
      {
        t.printStackTrace();
      }
}

}[/code]

Por que você tirou o waitFor() ?

Tente usar essa classe no lugar do Gobbler:

[code]
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;

public class StreamRedirector {
private Writer out;
private InputStream in;
private static ExecutorService redirectorPool = Executors.newCachedThreadPool(new ThreadFactory() {
public Thread newThread(Runnable r) {
Thread t = new Thread(r, “Stream Redirector”);
t.setDaemon(true);
return t;
}
});

private volatile boolean redirect = true;

public StreamRedirector(OutputStream out, InputStream in) {
    this(new PrintWriter(out), in);
}

public StreamRedirector(Writer out, InputStream in) {
    this.out = out;
    this.in = in;

    redirectorPool.execute(new RedirectorRun());
}

public void stopRedirect() {
    redirect = false;
}

private class RedirectorRun implements Runnable {
    public void run() {
        try {
            int nextByte = in.read();
            while (nextByte != -1 && redirect) {
                out.write(nextByte);
                nextByte = in.read();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

}[/code]

O código fica bem parecido:

[code]Runtime rt = Runtime.getRuntime();
Process proc = rt.exec( “/home/lbitt/Desktop/sleepLoop”);
StreamRedirector red = new StreamRedirector(System.out, proc.getInputStream());

proc.waitFor();
red.stopRedirect();[/code]

Só que essa thread não espera pelo \n, como o readLine() faz. Talvez o seu processo não tenha esse tipo de terminador.

Sim, ficou claro que é um problema no terminador do processo que eu chamo!
Eu alterei o código exemplo do artigo passado e funcionou, vou testar com esse que vc passou.
Obrigado pela ajuda!
E SIM eu li o artigo!!!

Eu escrevi esse StreamRedirector justamente para esse fim. Já usei em diversos projetos, com diversos programas. Certamente funciona.

Nosso programa permitia que o usuário escolhesse para onde redirecionar a saída. Podia ser tanto para um JTextArea, quando para o console, quanto para um arquivo de texto, ou até mesmo para um socket (ou mesmo, uma combinação de todos esses elementos).

Amigos,

estou precisando de algo que parece simples, mas estou pesquisando há alguns dias e não consigo resolver.

Tenho de abrir um arquivo da rede via samba. Consigo acessá-lo tranquilo, mas não consigo abri-lo.

Pela classe Desktop não consigo abri-lo, pois esta classe é para FILE. Não consigo pelo Process Builder porque estou no linux e preciso autenticar para ter acesso à pasta da rede.

Alguém pode me ajudar?

Grato.

Paulo