2008-10-11 14 views

Respuesta

3

Eche un vistazo a los documentos y fuente para - Estoy seguro de que podría escribir fácilmente una versión que solo use System.err en lugar de System.out. (Es una pena que ConsoleHandler no permita que esto se configure, para ser honesto.)

Luego es solo un caso de configurar el sistema de registro para usar su nuevo StdoutHandler (o como se llame) de la manera normal .

+0

Creo que ConsoleHandler es el predeterminado, hay un StreamHandler que puede imprimir en cualquier otra secuencia. – Uri

+3

Sí, pero querría crear una subclase de StreamHandler para evitar intentar cerrar System.err, sospecho. –

1

Si utiliza el registro de Java, puede cambiar el controlador predeterminado:

Por ejemplo, para los archivos: Handler fh = new FileHandler (ARCHIVO); Logger.getLogger (LOGGER_NAME) .addHandler (fh);

Si desea generar un flujo de salida, puede usar StreamHandler, creo que puede configurarlo con cualquier flujo de salida que desee, incluida la transmisión del sistema.

7

Me di cuenta de una forma. Primero elimine el controlador predeterminado de la consola:

setUseParentHandlers (false);

Entonces subclase ConsoleHandler y en el constructor:

setOutputStream (System.out);

+3

Es mejor que ajuste 'System.out' con' OutputStream' implementado automáticamente para evitar cerrarlo en la siguiente llamada a 'setOutputStream (...)' o 'LogManager.reset()'. – amotzg

+0

Además, tenga cuidado de no llamar al super constructor (de 'ConsoleHandler') ya que establece System.err y lo cerrará cuando llame a' setOutputStream (System.out) '. O bien, puede simplemente subclasificar 'StreamHandler' y llamar' super (OutputStream, Formatter) '. – amotzg

0

Si configura setUseParentHandlers (falso); solo esa clase lo tiene configurado. Otras clases en la aplicación todavía lo pasarán a stderr.

+0

Si uno hace eso para la clase de registro de raíz (Logger.GLOBAL_LOGGER_NAME), el registro de la consola está deshabilitado para todas las clases. – koppor

-1

Simplemente extienda StreamHandler & en la llamada del constructor Super (System.out,). Esto evitará el cierre de System.err - Gracias

9
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(){} 
     }; 
+6

Pero, en los tiempos modernos ... ¿hay alguna manera de hacerlo sin implementar un controlador personalizado? – Victor

10

he llegado a

SimpleFormatter fmt = new SimpleFormatter(); 
StreamHandler sh = new StreamHandler(System.out, fmt); 
logger.addHandler(sh); 
+1

Esto no deshabilita el controlador predeterminado. Solo sigue la respuesta http://stackoverflow.com/a/2533250/873282 – koppor

7

poco Hmm acabo de recibir en el pie un par de veces, tratando de lograr esta hazaña. Antes de googlear mi camino, logré conjurar el siguiente truco. Feo, pero parece hacer el trabajo.

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

Cuidado con: setOutputStream Calling() desde el constructor es tentador, pero sí (como Jon Skeet ya se señaló) cerca System.err. ¡Habilidades locas!

2

Si todavía hay alguien buscando una solución a este problema. Esto es lo que finalmente se me ocurrió: acabo de subclasificar StreamHandler y agregué un parámetro adicional MaxLevel, que se comprueba al comienzo de publish(). Si el nivel del evento de registro es mayor que MaxLevel, la publicación no se ejecutará más. Aquí están los detalles:

MaxlevelStreamHandler.java clase principal a continuación.

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(); 
    } 
} 

Clase Principal

Para mostrar ahora algunos eventos en la salida estándar y algunos en stderr, simplemente configuración dos StreamLoggers, uno de los eventos críticos y uno para todos los demás, y desactivar el registrador consola estándar:

// 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"); 

Hope this helps!

Actualización: Agregué super.flush() justo después de super.publish() para asegurarme de que el mensaje se muestra inmediatamente. Antes, tenía problemas con los mensajes de registro que siempre se mostraban al final. Ahora es parte del código anterior.

2

Tuve un problema similar. Quería registrar INFO y más abajo en System.out, y ADVERTENCIA y más arriba en System.err. Aquí está la solución implementé:

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(); 
     } 
    } 
} 

Por supuesto, usted podría hacerlo más flexible por factorización de la referencia codificada para Level.INFO, por ejemplo. Pero esto funcionó bien para obtener un registro básico de doble flujo. (Por cierto, los consejos sobre la no subclasificación de ConsoleHandler para evitar el cierre de System.err fueron muy útiles.)

+0

Perfecto. Hay que decir que los diseñadores no lo han facilitado ... ¿por qué no pueden anticipar esta necesidad? Ten en cuenta que parece ser lo mismo con otros marcos de trabajo: ¿tu primera tarea? ¡Salta a través de varios aros difíciles! –

1

ConsoleHandler capturará una instantánea de System.err durante la construcción. Una opción sería intercambiar la secuencia de error global con la salida global y luego crear ConsoleHandler.

final PrintStream err = System.err; 
System.setErr(System.out); 
ConsoleHandler h = new ConsoleHandler(); //Snapshot of System.err 
System.setErr(err); 

Esto asume que el código tiene permiso para modificar flujo de error y que ningún otro código que se ejecuta está accediendo al flujo de error. En resumen, esta es una opción, pero hay alternativas más seguras.

1

Cuando creamos un nuevo objeto ConsoleHandler, la secuencia de salida predeterminada es "system.err". Desafortunadamente, Java no proporciona ningún método público para que la clase ConsoleHandler establezca el flujo de salida. Por lo tanto, se puede establecer solo en el momento de la creación del objeto. Como la clase ConsoleHandler extiende StreamHandler, que tiene un método protegido "setOutputStream" para establecer la secuencia de salida explícitamente. Para configurar la salida Stream para ConsoleHandler, simplemente anule este método en el momento de la nueva llamada para la creación de objetos.

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