web-dev-qa-db-fra.com

Comment puis-je changer Java Sortie de la console de la console de STDRRR pour vous démarquer?

J'utilise la norme ConsoleHandler de Java.util.logging et par défaut, la sortie de la console est dirigée vers le flux d'erreur (I.E. System.err).

Comment modifier la sortie de la console dans le flux de sortie (c'est-à-dire System.out)?

30
Obediah Stane

Je suis arrivé à

 SimpleFormatter fmt = new SimpleFormatter();
 StreamHandler sh = new StreamHandler(System.out, fmt);
 logger.addHandler(sh);
14
Frank Vlach

Hmm je viens de prendre un peu dans le pied plusieurs fois, essayant d'accomplir cet exploit. Avant de googler mon chemin ici, j'ai réussi à évoquer le piratage suivant. Moche, mais il semble faire le travail.

public class StdoutConsoleHandler extends ConsoleHandler {
  protected void setOutputStream(OutputStream out) throws SecurityException {
    super.setOutputStream(System.out); // kitten killed here :-(
  }
}

SURVEILLER: Calling SetOutPutStream () à partir du constructeur est tentant, mais elle (comme Skeet Jon a déjà signalé) Fermer System.err. MAIN!

9
volley

J'ai compris une façon. Tout d'abord, supprimez le gestionnaire de la console par défaut:

setruenthandlers (faux);

Puis Sous-classe Consolehandler et dans le constructeur:

systeutPutStream (System.out);

9
Obediah Stane
Handler consoleHandler = new Handler(){
         @Override
            public void publish(LogRecord record)
            {
                if (getFormatter() == null)
                {
                    setFormatter(new SimpleFormatter());
                }

                try {
                    String message = getFormatter().format(record);
                    if (record.getLevel().intValue() >= Level.WARNING.intValue())
                    {
                        System.err.write(message.getBytes());                       
                    }
                    else
                    {
                        System.out.write(message.getBytes());
                    }
                } catch (Exception exception) {
                    reportError(null, exception, ErrorManager.FORMAT_FAILURE);
                }

            }

            @Override
            public void close() throws SecurityException {}
            @Override
            public void flush(){}
        };
9
Jeremiah Jahn

J'avais un problème similaire. Je voulais connecter des informations et ci-dessous pour System.out, et avertissement et ci-dessus à System.err. Voici la solution que j'ai implémentée:

public class DualConsoleHandler extends StreamHandler {

    private final ConsoleHandler stderrHandler = new ConsoleHandler();

    public DualConsoleHandler() {
        super(System.out, new SimpleFormatter());
    }

    @Override
    public void publish(LogRecord record) {
        if (record.getLevel().intValue() <= Level.INFO.intValue()) {
            super.publish(record);
            super.flush();
        } else {
            stderrHandler.publish(record);
            stderrHandler.flush();
        }
    }
}

Bien sûr, vous pouvez le rendre plus flexible en pratiquant la référence à codée dur à Level.INFO, par exemple. Mais cela a bien fonctionné pour moi d'obtenir une exploitation forestière de base à double courant. (BTW, les astuces sur NON SUBCLASSING ConsoleHandler pour éviter de fermer le System.err étaient très utiles.)

4
ocarlsen

Regardez les documents et la source pour ConsoleHandler - Je suis sûr que vous pourriez facilement écrire une version qui utilise simplement System.err au lieu de System.out. (C'est dommage que ConsoleHandler n'autorise pas cela à être configuré, d'être honnête.)

Ensuite, il s'agit simplement d'un cas de configuration du système de journalisation pour utiliser votre nouveau STDOUTHANDLER (ou tout ce que vous l'appelez) normalement.

3
Jon Skeet

S'il y a toujours quelqu'un à la recherche d'une solution à ce problème. Voici ce que j'ai proposé finalement: je viens de sous-classé Streamhandler et ajouté un paramètre supplémentaire Maxlevel, qui est vérifié au début de la publication (). Si le niveau de l'événement de journalisation est supérieur à la maxlevel, la publication ne sera plus exécutée. Voici les détails:

maxlevelstreamhandler.java classe principale ci-dessous.

package helper;

/**
 * The only difference to the standard StreamHandler is 
 * that a MAXLEVEL can be defined (which then is not published)
 * 
 * @author Kai Goergen
 */

import Java.io.PrintStream;
import Java.util.logging.Formatter;
import Java.util.logging.Level;
import Java.util.logging.LogRecord;
import Java.util.logging.StreamHandler;

public class MaxlevelStreamHandler extends StreamHandler {

    private Level maxlevel = Level.SEVERE;  // by default, put out everything

    /**
     * The only method we really change to check whether the message
     * is smaller than maxlevel.
     * We also flush here to make sure that the message is shown immediately.
     */
    @Override
    public synchronized void publish(LogRecord record) {
        if (record.getLevel().intValue() > this.maxlevel.intValue()) {
            // do nothing if the level is above maxlevel
        } else {
            // if we arrived here, do what we always do
            super.publish(record);
            super.flush();
        }
    }

    /**
     * getter for maxlevel
     * @return
     */
    public Level getMaxlevel() {
        return maxlevel;
    }

    /**
     * Setter for maxlevel. 
     * If a logging event is larger than this level, it won't be displayed
     * @param maxlevel
     */
    public void setMaxlevel(Level maxlevel) {
        this.maxlevel = maxlevel;
    }

    /** Constructor forwarding */
    public MaxlevelStreamHandler(PrintStream out, Formatter formatter) {
        super(out, formatter);
    }

    /** Constructor forwarding */
    public MaxlevelStreamHandler() {
        super();
    }
}

classe principale

Pour afficher maintenant des événements dans STDOUT et certains à StDeRR, définissez simplement deux streamloggers, un pour les événements critiques et un pour tous les autres, et désactivez l'enregistreur de console standard:

// setup all logs that are smaller than WARNINGS to stdout
MaxlevelStreamHandler outSh = new MaxlevelStreamHandler(System.out, formatter);
outSh.setLevel(Level.ALL);
outSh.setMaxlevel(Level.INFO);
logger.addHandler(outSh);

// setup all warnings to stdout & warnings and higher to stderr
StreamHandler errSh = new StreamHandler(System.err, formatter);
errSh.setLevel(Level.WARNING);
logger.addHandler(errSh);

// remove default console logger
logger.setUseParentHandlers(false);

logger.info("info");
logger.warning("warning");
logger.severe("severe");

J'espère que cela t'aides!

Mise à jour: j'ai ajouté Super.flush () juste après Super.Publish () pour vous assurer que le message est montré immédiatement. Auparavant, j'ai eu des problèmes que les messages de journal ont toujours été montrés à la fin. Il fait maintenant partie du code ci-dessus.

2
Kai

Lorsque nous créons un nouvel objet Consolehandler, le flux de sortie par défaut est "System.err". Tristement Java ne fournit aucune méthode publique de la classe ConsoleHandler pour définir le flux de sortie. Donc, il ne peut donc être défini qu'au moment de la création d'objets. Comme ConsoleHandler Class prolonge Streamhandler, qui a une méthode protégée. "SetOutputTretstream" pour définir le flux de sortie explicitement. Pour définir le flux de sortie pour ConsoleHandler, il suffit de remplacer cette méthode au moment du nouvel appel de la création d'objets.

ConsoleHandler consoleHandler = new ConsoleHandler (){
            @Override
            protected synchronized void setOutputStream(OutputStream out) throws SecurityException {
                super.setOutputStream(System.out);
            }
        };
1
Virendra Singh

La consolehandler prendra un instantané de System.err lors de la construction. Une option serait d'échanger le flux d'erreur global avec le flux mondial Out, puis de créer la consoleHandler.

ConsoleHandler h = null;
final PrintStream err = System.err;
System.setErr(System.out);
try {
    h = new ConsoleHandler(); //Snapshot of System.err
} finally {
    System.setErr(err);
}

Cela suppose que le code a la permission de modifier le flux d'erreur et qu'aucun autre code d'exécution n'accède au flux d'erreur. En bref, c'est une option mais il y a des alternatives plus sûres.

1
jmehrens

Si vous utilisez Java Logging, vous pouvez modifier le gestionnaire par défaut:

Par exemple, pour les fichiers: gestionnaire FH = nouveau fichierHandler (nom de fichier); LOGGER.GETLOGER (NOME LOGGER_NAME) .ADDHANDLER (FH);

Si vous souhaitez sortir à un flux, vous pouvez utiliser Streamhandler, je pense que vous pouvez le configurer avec n'importe quel flux de sortie que vous souhaitez, y compris le flux système.

1
Uri

Si vous définissez SETUTUSEPEPHANDLERS (FALSE); Seule cette classe l'a définie. D'autres classes de l'application vont toujours passer à Sterdr.

0
Val