Visualizzazione dei risultati da 1 a 7 su 7
  1. #1
    Utente di HTML.it
    Registrato dal
    Oct 2014
    residenza
    Padova
    Messaggi
    361

    Eseguire classe java con ProcessBuilder

    Ciao a tutti, da una vecchia discussione trovata mi è venuta voglia di provare ad eseguire comandi di sistema tramite java, per farlo sto usando le classi ProcessBuilder e Process.

    Ho trovato esempi di codice in cui si prova a compilare ed eseguire una classe esterna con ProcessBuilder, sistemando qua e là sono arrivato a questo:

    codice:
    import java.lang.ProcessBuilder;
    import java.io.*;
    public class Pb
    { 
        public static void main(String [] args) throws IOException
        {        
            String mainClass="Prova",directory="G:/sparsiJava";
            ProcessBuilder cmd = new ProcessBuilder(new String[]{"cmd","/c","javac "+mainClass+".java"});        
            cmd.directory(new File(directory));
            cmd.redirectErrorStream(true);
            try
            {
                Process process=cmd.start();
                InputStream is=process.getInputStream();
                InputStreamReader isr=new InputStreamReader(is);
                BufferedReader br=new BufferedReader(isr);
                String line,errori="";
                while((line=br.readLine())!=null)errori+=line+"\n";
                if(process.waitFor()==0)
                {
                    process.destroy();
                    cmd=new ProcessBuilder(new String[]{"cmd","/c","java "+mainClass});
                    cmd.directory(new File(directory));
                    process=cmd.start();
                    process.waitFor();
                    process.destroy();
                }
                else
                {
                    System.out.print("\nErrori in compilazione:\n\n"+errori);
                }                
            }
            catch(InterruptedException ex){}
        }
    }
    A me sembra funzionare, è un buon modo di procedere o si potrebbe far di meglio (che non sia troppo complicato ) ?

    Infine, un punto che non riesco a risolvere: supponiamo che la classe Prova richieda l'inserimento di variabili, che io leggevo prima con Scanner, è possibile passare le variabili quando richieste con ProcessBuilder, ma non al momento di far partire il processo ?

    Se ad esempio ho una classe Prova così costruita (Tanto per fare un esempio banale):

    codice:
    import java.util.Scanner;
    public class Prova
    {
        public static void main(String[] args)
        {
            String scelta="";
            while(scelta!=null)
            {
                System.out.print("\n\nChe operazione vuoi effettuare (1: somma 2: differenza) ? > ");
                Scanner scan=new Scanner(System.in);
                scelta=scan.nextLine();
                if(!scelta.equals("1")&&!scelta.equals("2"))return;
                System.out.print("\nInserisci il primo intero > ");
                int u=scan.nextInt();
                System.out.print("\nInserisci il secondo intero > ");
                int d=scan.nextInt();
                if(scelta.equals("1"))System.out.print("\nLa somma dei due interi e': "+(u+d));
                else System.out.print("\nLa differenza dei due interi e': "+(u-d));
            }
        }
    }
    Posso gestire il flusso del programma tramite il ProcessBuilder ?

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Innanzitutto javac/java sono già "eseguibili", non c'è bisogno di passare per la shell di Windows (cmd.exe).

    Poi comunque i tre stream standard-input/output/error del processo lanciato sono di per sé normalmente rediretti verso la applicazione Java. Questo vuol dire che se il processo lanciato fa output su output/error allora lato Java lo devi leggere. E se invece richiede input su standard-input, allora lato Java devi "pilotarlo" scrivendoci qualcosa tu.

    Comunque da Java 7 ProcessBuilder ha una feature interessante: il metodo inheritIO() che permette di "ereditare" i tre stream dalla applicazione Java. Quindi se la tua applicazione Pb la lanci da una console, il processo lanciato userebbe quella console, senza dover andare a maneggiare direttamente gli stream.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  3. #3
    Utente di HTML.it
    Registrato dal
    Oct 2014
    residenza
    Padova
    Messaggi
    361
    Grazie andbin, appena posso controllo inheritIO.

    Scusa la mia ignoranza,ma non ho afferrato le prime due righe.
    Ho visto che al costruttore di processBuilder venivano anche passate solo le stringhe "java" ,"nomeClasse" ti riferisci a quello?

  4. #4
    Utente di HTML.it
    Registrato dal
    Oct 2014
    residenza
    Padova
    Messaggi
    361
    Edit: inviato per sbaglio 2 volte,colpa dello smartphone��
    Ultima modifica di Ansharja; 09-09-2015 a 21:48

  5. #5
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da Ansharja Visualizza il messaggio
    Scusa la mia ignoranza,ma non ho afferrato le prime due righe.
    Ho visto che al costruttore di processBuilder venivano anche passate solo le stringhe "java" ,"nomeClasse" ti riferisci a quello?
    {"cmd","/c","javac "+mainClass+".java"}

    cmd è (cmd.exe) la shell di Windows (con parametro /c ). Non servirebbe di per sé. Sarebbe sufficiente:
    { "javac", mainClass+".java" }
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  6. #6
    Utente di HTML.it
    Registrato dal
    Oct 2014
    residenza
    Padova
    Messaggi
    361
    Ok avevo intuito allora.
    Grazie mille ☺

  7. #7
    Utente di HTML.it
    Registrato dal
    Oct 2014
    residenza
    Padova
    Messaggi
    361
    Quote Originariamente inviata da andbin Visualizza il messaggio
    Comunque da Java 7 ProcessBuilder ha una feature interessante: il metodo inheritIO() che permette di "ereditare" i tre stream dalla applicazione Java. Quindi se la tua applicazione Pb la lanci da una console, il processo lanciato userebbe quella console, senza dover andare a maneggiare direttamente gli stream.
    Ho provato il metodo inheritIO() e funziona correttamente, grazie della dritta

    Quote Originariamente inviata da andbin Visualizza il messaggio
    Poi comunque i tre stream standard-input/output/error del processo lanciato sono di per sé normalmente rediretti verso la applicazione Java. Questo vuol dire che se il processo lanciato fa output su output/error allora lato Java lo devi leggere. E se invece richiede input su standard-input, allora lato Java devi "pilotarlo" scrivendoci qualcosa tu.
    Ho provato a seguire anche questa indicazione nel caso non possa usare inheritIO, ad esempio se volessi gestire processBuilder da una GUI.
    Dicevi di "pilotare" l'input che il programma si aspetta e io ho provato a farlo così:

    codice:
    OutputStreamWriter osr=new OutputStreamWriter(os);
    BufferedWriter writer=new BufferedWriter(osr); writer.write("2"); writer.flush(); writer.close(); Scanner scanner = new Scanner(isr); // isr era l'InputStreamReader while(scanner.hasNextLine()) System.out.println(scanner.nextLine());
    Il problema è che questo tipo di codice inserisce l'input (che tra l'altro non viene visualizzato) ma poi il loop continua e ottengo un errore.

    E' possibile riuscire a inserire l'input nel momento in cui il processo lo richiede (sempre senza usare inheritIO) ?

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.