IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Entrée/Sortie Java Discussion :

Runtime.getRuntime().exec() vers ProcessConsumer


Sujet :

Entrée/Sortie Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    268
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 268
    Par défaut Runtime.getRuntime().exec() vers ProcessConsumer
    Après avoir lu le blog d'adiGuba (un grand merci !) j'en renvoie à mon histoire de Lancement d'un batch.
    Mon problème maintenant, c'est de récupérer les flux. Avant, avec Runtime.exec(), je faisais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    	String ligneOK;
    	BufferedReader sortie = new BufferedReader(new InputStreamReader(proc.getInputStream()));
    	while ( (ligneOK = sortie.readLine()) != null ) {
    		this.log(" "+ligneOK);
    	}
    	sortie.close();
    et pareil pour le stream d'erreur.

    Mais maintenant, (avec l'aide donc d'adiGuba et de mon ancien post), je tente de faire la même chose, mais j'obtiens une erreur "Stream closed".

    La partie
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    	monPC.output( new FileOutputStream("out.txt") ).error( new FileOutputStream("err.txt") )
    n'est donc pas intéressante puisque je ne veux pas des fichiers.
    Cependant, les fichiers sont crées, donc ça marche.

    J'essaie donc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    	// On crée les StringBuilder qui contiendront les sorties du process :
    	StringBuilder out = new StringBuilder();
    	StringBuilder err = new StringBuilder();
    mais du coup, je ne sais pas du tout comment traiter mes "BufferedReader sortie" (celui du runtime.exec() normal).
    Je tiens à préciser que je ne maitrise pas du tout toutes ces notions de buffer, et que je sais pas trop quoi chercher

    [Edit]
    Après un peu plus de recherche, et toujours sur le blog, je test :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    	PipedReader lignesOk = new PipedReader(); 
    	PipedReader lignesErr = new PipedReader(); 
     
    	pc.output(new PipedWriter(lignesOk)).error(new PipedWriter(lignesErr));
    mais le
    reste toujours bloqué, comme avant (comme par un ancien proc.waitFor()), et apparement toujours au moment du remplissage des flux. Je me doute que le problème vient de la ligne de commande, mais pourquoi dans le cas de fichiers, ça marche, alors qu'avec des readers/writer ça ne marche plus ???

    Suis-je obligé de passer par des fichiers temporaires que je lirais après le "monPC.consume()" ?

  2. #2
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Salut,

    Si tu utilises des StringBuilder il te suffit de lire la chaine générée qui contiendra la totalité de la réponse (mais cela peut être consommateur de mémoire si la sortie est très grande).

    Si tu utilises des PipedReader/Writer tu dois faire un consumeInBackground() car la lecture doit être faite en parallèle... mais cela revient au même problème qu'à l'origine...


    Sinon si tu as un besoin plus spécifique tu peux définir tes propres "appender".



    D'où ma question : que va tu faire des données en sortie ?


    a++

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    268
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 268
    Par défaut
    Alors, en passant par des fichiers (avec lecture tout de suite après), celà fonctionne.

    Mais avec PipedReader/Writer en consumeInBackground(), toujours le même problème. Et je serais totalement incapable de définir mes propres "appender".

    [EDIT]
    En fait non, l'appli se bloque sur le
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    // lignesOk est le PipedReader
    BufferedReader sortie = new BufferedReader(lignesOk);
    while ( (ligneOK = sortie.readLine()) != null )
    // etc ...
    Ce qui est bizarre, c'est que suivant ce que donne le batch, il bloque soit au flux, soit à l'exécution (que ce soit runtime.exec() ou ta librairie) (sauf dans le cas où les flux sont des fichiers, comme je l'ai dis précédement)
    [/EDIT]

    Les données en sorties sont en fait pour un affichage dans un compte rendu de l'application.


    Petite remarque : Je test donc en passant par des fichiers. Mon batch est du style :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    @echo off
    echo lancement
    "c:/BLABLABLA/prog.exe"
    echo termine
    J'ai bien les 2 echo dans le "output", mais l'affichage du "prog.exe" part directement dans le "error"

  4. #4
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par JohnNC Voir le message
    Mais avec PipedReader/Writer en consumeInBackground(), toujours le même problème.
    Comme tu utilises cela sur les 2 sorties (standards et erreurs), il faut créer deux threads de lecture sinon tu peux avoir des interblocages (cela revient au même problème qu'utilsier exec() directement).


    Citation Envoyé par JohnNC Voir le message
    Les données en sorties sont en fait pour un affichage dans un compte rendu de l'application.
    Oui mais comment ?
    Dans tous tes codes tu essayes de faire des lectures lignes par lignes ? C'est une volonté particulière ou pas ?

    Citation Envoyé par JohnNC Voir le message
    J'ai bien les 2 echo dans le "output", mais l'affichage du "prog.exe" part directement dans le "error"
    Ca ca dépend complètement de ton "prog.exe"...


    a++

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    268
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 268
    Par défaut
    Désolé j'ai fais une petite édition entre temp, sur le "blocage".

    Alors :
    Citation Envoyé par adiGuba Voir le message
    Oui mais comment ?
    Dans tous tes codes tu essayes de faire des lectures lignes par lignes ? C'est une volonté particulière ou pas ?
    par un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    String ligneOK;
    BufferedReader sortie = new BufferedReader(lignesOk);
    //BufferedReader sortie = new BufferedReader(new InputStreamReader(new FileInputStream(ficSTD)));
    while ( (ligneOK = sortie.readLine()) != null ) {
      // cr est un objet de compteRendu : un JPanel avec un JTextPane
      cr.log(" "+ligneOK);
    }
    sortie.close();
    // Suivi de
    String ligneErreur;
    BufferedReader sortieErr = new BufferedReader(lignesErr);
    //BufferedReader sortieErr = new BufferedReader(new InputStreamReader(new FileInputStream(ficERR)));
    while ( (ligneErreur = sortieErr.readLine()) != null ) {
      cr.logErreur(" "+ligneErreur);
    }
    sortieErr.close();
    Et ligne par ligne, heu bah parceque celui qui travaillait avant moi faisait comme ça et que j'ai copié/collé

    Citation Envoyé par adiGuba Voir le message
    Ca ca dépend complètement de ton "prog.exe"...
    Ben là, je vais laisser comme ça alors (il s'agit de pg_restore de postgres).

  6. #6
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Si c'est pour afficher la sortie dans un JTextPane tu peux l'y envoyer directement plutôt que de faire une lecture ligne par ligne.


    Il te suffit d'implémenter l'interface Appendable et ses méthodes append(), sachant que ces méthodes seront appelées lorsque des données seront lu depuis le process, ce qui peut donner :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    class DocumentAppendable implements Appendable {
     
    	private final JTextComponent textComponent;
     
    	public DocumentAppendable(JTextComponent component) {
    		this.textComponent = component;
    	}
     
    	/**
             * Insertion d'un chaine dans un document,
             * en déplacant les scrollbars si neccessaire
             */
    	private void insertString(final String text) {
    		SwingUtilities.invokeLater(new Runnable() {
    			public void run() {
    				// On récupèrel e composant graphique
    				JTextComponent comp = DocumentAppendable.this.textComponent;
    				// On récupère le document associé
    				Document doc = comp.getDocument();
    				try {
    					// On insert le text recu à la fin du document :
    		            doc.insertString(doc.getLength(), text, null);
    		            // Et on déplace les scrollbars :
    		            comp.scrollRectToVisible( comp.modelToView(doc.getLength()));
    		        } catch (BadLocationException e) {
    		        	throw new RuntimeException(e); // Ne devrait pas arriver
    		        }
    			}
    		});
    	}
     
     
    	/*
    	 * On implémente les diverses méthodes de l'interface Appendable
    	 * en se contentant de renvoyer vers la méthode insertString() :
    	 * 
    	 */
     
    	public Appendable append(char c) throws IOException {
    		insertString(Character.toString(c));
    		return this;
    	}
    	public Appendable append(CharSequence csq) throws IOException {
    		insertString(csq.toString());
    		return this;
    	}
    	public Appendable append(CharSequence csq, int start, int end) throws IOException {
    		insertString(csq.subSequence(start, end).toString());
    		return this;
    	}
    }
    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    	sh.command("ma ligne de commande")
    		// On redirige la sortie standard vers le textpane
    		.output(new DocumentAppendable(monTextPane))
    		// On redirige la sortie d'erreur vers la sortie standard
    		.errorRedirect() 
    		.consume();

    a++

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Système][Runtime]getRuntime().exec
    Par Neptune8 dans le forum API standards et tierces
    Réponses: 11
    Dernier message: 22/02/2011, 19h34
  2. Runtime.getRuntime().exec sous linux
    Par syl2095 dans le forum API standards et tierces
    Réponses: 1
    Dernier message: 30/01/2007, 12h56
  3. Runtime.getRuntime().exec(String) méthode sort
    Par devAd dans le forum Langage
    Réponses: 4
    Dernier message: 28/11/2006, 13h53
  4. [Runtime.getRuntime().exec] ouvrir un fichier ??
    Par miloud dans le forum API standards et tierces
    Réponses: 4
    Dernier message: 29/03/2006, 14h23
  5. [Swing] execution avec Runtime.getRuntime().exec
    Par benssj5 dans le forum AWT/Swing
    Réponses: 9
    Dernier message: 25/08/2004, 14h54

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo