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

Langage Java Discussion :

Redirection du flux de sortie


Sujet :

Langage Java

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    389
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2009
    Messages : 389
    Par défaut Redirection du flux de sortie
    Bonjour,
    actuellement, les logs de connexion ftp de mon application sont dirigées dans la console (avec System.out.println() ).

    Je voudrai, dans un premier temps, rediriger tout le texte dans un JTextField.
    Ensuite, je le redirigerai dans un fichier de log, mais pour l'instant, j'ai besoin d'afficher ces résultats directement sur l'application, et plus dans la console.

    Comment m'y prendre?

    Merci.

  2. #2
    Membre Expert
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 277
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 277
    Par défaut
    Tu peux utiliser la méthode setText de ton JTextField.
    Si tu as beaucoup de log, utilise un JTextArea ou un autre composant texte.

    Tu peux, en plus, utiliser une API de logs comme Log4j qui te facilitera l'écriture dans des fichiers.

  3. #3
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    je rajouterais que si tu ne veux pas modifier ton code (le System.out.println()) dans un premier temps, tu peux faire un System.setOut() auquel tu passe ta propre implémentation de outputstream.

  4. #4
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    389
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2009
    Messages : 389
    Par défaut
    Merci pour vos conseils

    Je vais plutot mettre ça dans un JTextAera effectivement, ça sera plus lisible.

    Concernant l'implémentation de outpustream, je dois organiser ça comment? Un peu de la même façon que lorsqu'on implémente la méthode toString(), ou c'est différent?

  5. #5
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    tu implémente les méthode de l'interface.

  6. #6
    Membre Expert
    Avatar de professeur shadoko
    Homme Profil pro
    retraité nostalgique Java SE
    Inscrit en
    Juillet 2006
    Messages
    1 257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 77
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : retraité nostalgique Java SE

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 257
    Par défaut
    une idée en passant (jai jamais fait mais dans ce cas ça me démangerait)
    faire un PipedInputStream dans un Thread qui lit le PipedOutputStream alimenté par SetOut.
    en faisant un joli petit code qui peut soit afficher quelque part (TexField par ex.) soit repasser une patate chaude au système de log (ne pas réécrer l'infrastructure de log!).

  7. #7
    Membre averti
    Développeur informatique
    Inscrit en
    Mars 2009
    Messages
    54
    Détails du profil
    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2009
    Messages : 54
    Par défaut
    Bonjour,

    en effet il est toujours possible de rediriger tes logs ou autres vers un Printstream particulier.

    voir la réponse de David Demner:
    http://www.coderanch.com/t/275028/St...ect-system-out

    En gros on surcharge la classe JTextField par exemple et on redéfinit la fonction println en lui passant le Printstream de notre choix (System.out par exemple).

    Ensuite, on redirige le outputStream via: System.setOut(monObjet.getPrintstream());

    Et tous les System.out.println() suivants seront envoyés au composant dont la fonction println se charge d'en mettre à jour le contenu.

  8. #8
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    389
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2009
    Messages : 389
    Par défaut
    En suivant vos conseils, j'ai remplacé les System.out.println() par des JTextArea.appen().

    Le texte s'affiche bien dans le textarea, mais le souci, c'est que l'application attend de charger tout le texte avant l'affichage.
    Ce que je voudrai, c'est que le texte d'affiche en temps réel, de la même façon que dans la console.

    Est-ce possible?

    Merci

  9. #9
    Membre Expert
    Avatar de professeur shadoko
    Homme Profil pro
    retraité nostalgique Java SE
    Inscrit en
    Juillet 2006
    Messages
    1 257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 77
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : retraité nostalgique Java SE

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 257
    Par défaut
    C'est pour cela que j'ai conseillé un Thread d'affichage distinct qui consomme les println "poussé" par un autre Thread... (PipedStream ne vous plait pas?)

  10. #10
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    389
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2009
    Messages : 389
    Par défaut
    Citation Envoyé par professeur shadoko Voir le message
    C'est pour cela que j'ai conseillé un Thread d'affichage distinct qui consomme les println "poussé" par un autre Thread... (PipedStream ne vous plait pas?)
    Je n'ai pas encore eu l'occasion d'utiliser les thread en java, est-ce compliqué à mettre en place? Car là, le rendu n'est vraiment pas agréable.

    Je suis pret à utiliser cette méthode, mais je ne voudrai pas perdre trop de temps avec ça.

  11. #11
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    Citation Envoyé par floctc Voir le message
    le souci, c'est que l'application attend de charger tout le texte avant l'affichage.
    1) tu ne dois pas faire ton travail principal (celui qui au final génère des messages de logs) dans le EDT, sinon tu givre ton affichage pendant l'opération
    2) tu dois faire les mises à jour du jtextare (appel à append) dans l'EDT, via des appel à swingworker par exemple


    En conclusion, ton code d'affichage devrais ressembler à ca

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    public void append(String text){
        SwingUtilities.invokeLater(new Runnable(){
            String message=text;
            public void run(){
              textarea.append(message);
            }
        }
    }

  12. #12
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    389
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2009
    Messages : 389
    Par défaut
    Merci de ton aide, tchize.

    J'ai repris ton code, mais je n'obtiens pas de meilleurs résultats. Je pense que je m'y prends mal, voici mon code :

    Code java : 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
     
    public void append(final String text){
    	 SwingUtilities.invokeLater(new Runnable(){
    	        String message=text;
    	        public void run(){
    	          textarea.append(message);
    	        }
    	    });
    	}
    	private void connect() {
    try {
     
    	//au lieu de textarea.append
    	append("Connexion à " + serverName + "\n");
    	ftp.connect(serverName);
    ...
    } catch (Exception e) {
    	e.printStackTrace();}
    }

    Où cela coince-t-il?

  13. #13
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483

  14. #14
    Membre Expert
    Avatar de professeur shadoko
    Homme Profil pro
    retraité nostalgique Java SE
    Inscrit en
    Juillet 2006
    Messages
    1 257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 77
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : retraité nostalgique Java SE

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 257
    Par défaut
    un peu plus compliqué, optimisable mais une illustration de ce que je voulais dire:
    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
     
    public interface Consommateur<X> {
    	public void consomme(X arg) ;
    }
     
    public class DetourneOut implements Runnable {
    	private BufferedReader bufr;
    	private Consommateur<String> évacuation;
     
    	public DetourneOut(Consommateur<String> consoString) {
    		this.évacuation = consoString ;
    		PipedInputStream pipIn = new PipedInputStream() ;
    		// on devrait mettre un petit buffer
    		bufr = new BufferedReader(new InputStreamReader(pipIn)) ;
    		try {
    		PipedOutputStream pipOut = new PipedOutputStream(pipIn) ;
                           // pour le printstream mettre flush à true
    		System.setOut(new PrintStream(pipOut));
    		} catch (IOException exc) {
    			 // au rapport!
    		}
    	}
     
    	public void run() {
    		String lu = null;
    		try {
    			while (null != (lu = bufr.readLine()))   {
    				évacuation.consomme(lu);
    			}
    		} catch (IOException exc) {
    			// AU RAPPORT!
    		}
    	}
    }
    un consommateur de trace :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    public class AfficheurTrace extends Panel implements Consommateur<String> {
    	private TextField afficheur = new TextField(60) ;
    	public AfficheurTrace() {
    		this.add(afficheur) ;
    	}
     
    	public void consomme(String trace){
    		this.afficheur.setText(trace) ;	
    	}
    }
    un main de test simplifié
    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
     
     
    	public static void main(String[] args) throws Exception {
    		AfficheurTrace afficheur = new AfficheurTrace();
    		final Frame fen = new Frame("test trace");
    		fen.addWindowListener(new WindowAdapter() { ...//etc/etc.
    		});
    		fen.add(afficheur) ;
    		fen.pack() ;
    		fen.setVisible(true) ;
    		DetourneOut detourneur = new DetourneOut(afficheur) ;
    		Thread th = new Thread(detourneur) ; // daemon probable
    		th.start() ;
    		System.out.println(" PREMIER MESSAGE");
    		Thread.sleep(500) ;
    		System.out.println(" DUEXIEME MESSAGE");
    	}

  15. #15
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    un autre exemple, tant qu'on y est. Des pipedstream, un textarea et le tour est joué


    Code java : 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
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    import java.awt.Dimension;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.PipedInputStream;
    import java.io.PipedOutputStream;
    import java.io.PrintStream;
    import java.io.Reader;
    import java.lang.reflect.InvocationTargetException;
     
    import javax.swing.JFrame;
    import javax.swing.JScrollPane;
    import javax.swing.JTextArea;
    import javax.swing.SwingUtilities;
     
     
    public class TestRedirect {
            // classe qui lint un pipedstream et écrit le texte dans un jtextarea
    	public static class Redirector implements Runnable{
    		// petite classe nécessaire à swingutilities pour travailler dans l'EDT ;)
    		private final class DoAppend implements Runnable {
    			private String text;
     
    			public DoAppend(String text) {this.text=text;}
    			@Override
    			public void run() {
    				 destination.append(text);
    			}
    		}
     
    		private JTextArea destination;
    		private Reader source;
    		public Redirector(JTextArea destination) throws IOException{
    			this.destination=destination;
    			PipedInputStream pis = new PipedInputStream();
    			PipedOutputStream pos = new PipedOutputStream(pis);
    			source = new InputStreamReader(pis,"UTF-8");
    			System.setOut(new PrintStream(pos,true,"UTF-8"));
    		}
     
    		@Override
    		public void run() {
    			try {
    				char[] buffer = new char[200];
    				while(true){
    					int size = source.read(buffer);
    					if (size>0)
    						SwingUtilities.invokeAndWait(new DoAppend(new String(buffer,0,size)));
    				}
    			} catch (IOException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			} catch (InterruptedException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			} catch (InvocationTargetException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    		}
     
    	}
    	public static void main(String[] argv){
    		JFrame f = new JFrame("test");
    		f.setSize(new Dimension(300,200));
    		JTextArea console = new JTextArea();
    		f.getContentPane().add(new JScrollPane(console));
    		try {
    			new Thread(new Redirector(console)).start();
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		f.setVisible(true);
    		for (int i=0; i< 50;i++){
    			System.out.println("Ligne "+i);
    			try {
    				Thread.sleep(2000);
    			} catch (InterruptedException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    		}
     
    	}
    }

  16. #16
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    389
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2009
    Messages : 389
    Par défaut
    Merci de vos solutions! Ca va même au dela de ce que j'attendais

    Ca fonctionne bien, mais j'aimerai comprendre certaines choses :
    dans mon code, j'ai une méthode init() qui instancie tous les objets graphiques.
    Cette méthode appelle une méthode connect(), qui contient donc mes System.out.prontln(...) .

    Si je veux utiliser la méthode append(), par exemple, proposée plus haut par tchize, comment faire pour l'appeler hors de l'EDT?

    J'ai du mal à appliquer le principe des threads, et j'aimerai réussir de moi-même

  17. #17
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    Citation Envoyé par floctc Voir le message

    Si je veux utiliser la méthode append(), par exemple, proposée plus haut par tchize, comment faire pour l'appeler hors de l'EDT?
    Tu ne peux pas, tous les composant visibles (c'est donc le cas de ton textarea) doivent etre manipulés depuis l'EDT, d'ou l'utilisation, dans mon cas, de SwingUtilities.invokeLater() qui appelera ce bout de code dans le thread de l'EDT quand il aura de la place pour le faire.

  18. #18
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    389
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2009
    Messages : 389
    Par défaut
    D'accord, merci de ton aide, j 'y vois plus clair.

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

Discussions similaires

  1. Redirection d'un flux de sortie system vers widget text
    Par bennyben87 dans le forum Interfaces Graphiques
    Réponses: 21
    Dernier message: 26/05/2010, 09h35
  2. Awk - changer le flux de sortie
    Par Longrais dans le forum Linux
    Réponses: 1
    Dernier message: 16/08/2005, 18h11
  3. [reseaux] redirection de flux
    Par Olive1808 dans le forum Programmation et administration système
    Réponses: 2
    Dernier message: 12/08/2002, 10h24

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