Cómo escribir registros en un archivo de texto cuando se usa java.util.logging.Logger

147

Tengo una situación en la que quiero escribir todos los registros creados por mí en un archivo de texto.

Estamos utilizando la API java.util.logging.Logger para generar los registros.

Lo intenté:

private static Logger logger = Logger.getLogger(className.class.getName());
FileHandler fh;   
fh = new FileHandler("C:/className.log");   
logger.addHandler(fh); 

Pero aún obtengo mis registros solo en la consola ...

Pankaj
fuente
posible duplicado de la API de registro
Raedwald
2
Varias respuestas sugieren usar FileHandler, como originalmente intentabas hacer. Una cosa a tener en cuenta (una lección dolorosamente aprendida): FileHandler está sincronizado . Lo que significa que, en una aplicación altamente multiproceso, todo lo que necesita para tener un punto muerto potencial es pasar un objeto a registrar cuyo método toString () llama a un método sincronizado. Cuidado con FileHandler.
Tim Boudreau

Respuestas:

238

Prueba esta muestra. Esto funciona para mi.

public static void main(String[] args) {  

    Logger logger = Logger.getLogger("MyLog");  
    FileHandler fh;  

    try {  

        // This block configure the logger with handler and formatter  
        fh = new FileHandler("C:/temp/test/MyLogFile.log");  
        logger.addHandler(fh);
        SimpleFormatter formatter = new SimpleFormatter();  
        fh.setFormatter(formatter);  

        // the following statement is used to log any messages  
        logger.info("My first log");  

    } catch (SecurityException e) {  
        e.printStackTrace();  
    } catch (IOException e) {  
        e.printStackTrace();  
    }  

    logger.info("Hi How r u?");  

}

Produce la salida en MyLogFile.log

Apr 2, 2013 9:57:08 AM testing.MyLogger main  
INFO: My first log  
Apr 2, 2013 9:57:08 AM testing.MyLogger main  
INFO: Hi How r u?

Editar:

Para quitar el controlador de la consola, use

logger.setUseParentHandlers(false);

dado que ConsoleHandler está registrado con el registrador principal del que derivan todos los registradores.

Sri Harsha Chilakapati
fuente
1
Me está funcionando ... Pero también estoy obteniendo registros en la consola. ¿Cómo eliminarlo desde allí?
Pankaj
¿Podría sugerirme qué hacer si quiero mantener todos los registros? En realidad, desde este enfoque, ¿mi archivo de texto está siendo reemplazado si ejecuto mi aplicación por segunda vez?
Pankaj
1
Cómo hacer eso ... Lo busqué en Google pero encontré tantos códigos confusos ... ¿Podrían ayudarme? ...
Pankaj
77
@bluemunch Puede usar el constructor alternativo de FileHandler(path, true)para hacer que el registro se anexe al archivo de registro existente.
Sri Harsha Chilakapati
1
@Línea Sí. Para este caso, generalmente mantengo un método de utilidad de creación de registro.
Sri Harsha Chilakapati
16

En primer lugar, ¿dónde definió su registrador y desde qué clase \ método intenta llamarlo? Hay un ejemplo de trabajo, recién horneado:

public class LoggingTester {
    private final Logger logger = Logger.getLogger(LoggingTester.class
            .getName());
    private FileHandler fh = null;

    public LoggingTester() {
        //just to make our log file nicer :)
        SimpleDateFormat format = new SimpleDateFormat("M-d_HHmmss");
        try {
            fh = new FileHandler("C:/temp/test/MyLogFile_"
                + format.format(Calendar.getInstance().getTime()) + ".log");
        } catch (Exception e) {
            e.printStackTrace();
        }

        fh.setFormatter(new SimpleFormatter());
        logger.addHandler(fh);
    }

    public void doLogging() {
        logger.info("info msg");
        logger.severe("error message");
        logger.fine("fine message"); //won't show because to high level of logging
    }
}   

En su código olvidó definir el formateador, si necesita uno simple puede hacerlo como mencioné anteriormente, pero hay otra opción, puede formatearlo usted mismo, hay un ejemplo (simplemente insértelo en lugar de esta línea fh .setFormatter (nuevo SimpleFormatter ()) siguiente código):

fh.setFormatter(new Formatter() {
            @Override
            public String format(LogRecord record) {
                SimpleDateFormat logTime = new SimpleDateFormat("MM-dd-yyyy HH:mm:ss");
                Calendar cal = new GregorianCalendar();
                cal.setTimeInMillis(record.getMillis());
                return record.getLevel()
                        + logTime.format(cal.getTime())
                        + " || "
                        + record.getSourceClassName().substring(
                                record.getSourceClassName().lastIndexOf(".")+1,
                                record.getSourceClassName().length())
                        + "."
                        + record.getSourceMethodName()
                        + "() : "
                        + record.getMessage() + "\n";
            }
        });

O cualquier otra modificación, lo que quieras. Espero eso ayude.

DenisD
fuente
9

La ubicación del archivo de registro se puede controlar mediante el archivo logging.properties. Y se puede pasar como parámetro JVM ej:java -Djava.util.logging.config.file=/scratch/user/config/logging.properties

Detalles: https://docs.oracle.com/cd/E23549_01/doc.1111/e14568/handler.htm

Configurar el controlador de archivos

Para enviar registros a un archivo, agregue FileHandler a la propiedad de controladores en el archivo logging.properties. Esto habilitará el registro de archivos a nivel mundial.

handlers= java.util.logging.FileHandler Configure el controlador estableciendo las siguientes propiedades:

java.util.logging.FileHandler.pattern=<home directory>/logs/oaam.log
java.util.logging.FileHandler.limit=50000
java.util.logging.FileHandler.count=1
java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter

java.util.logging.FileHandler.pattern especifica la ubicación y el patrón del archivo de salida. La configuración predeterminada es su directorio de inicio.

java.util.logging.FileHandler.limit especifica, en bytes, la cantidad máxima que el registrador escribe en cualquier archivo.

java.util.logging.FileHandler.count especifica cuántos archivos de salida recorrer.

java.util.logging.FileHandler.formatter especifica la clase de formateador java.util.logging que la clase de controlador de archivos utiliza para formatear los mensajes de registro. SimpleFormatter escribe resúmenes breves "legibles para humanos" de registros de anotaciones.


Para indicar a Java que use este archivo de configuración en lugar de $ JDK_HOME / jre / lib / logging.properties:

java -Djava.util.logging.config.file=/scratch/user/config/logging.properties
Awanish Kumar
fuente
Gran respuesta, por lo que veo, la única global. Decidí cambiar logging.properties en JDK (aunque en Java 11, se encuentran en el directorio conf del directorio de instalación de Java). Vale la pena señalar que la ubicación predeterminada de dicho archivo de registro será user.home / javaX.log (donde user.home es la propiedad del sistema, y ​​X es el siguiente número en orden; para el primero será 0).
Línea
5

Una buena biblioteca disponible llamada log4j para Java .
Esto proporcionará numerosas características. Vaya a través del enlace y encontrará su solución.

Chintan Rathod
fuente
Ya existe log4j2 pero debe configurarse a nivel de proyecto
Pini Cheyni
5

Tal vez esto es lo que necesitas ...

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

/**
 * LogToFile class
 * This class is intended to be use with the default logging class of java
 * It save the log in an XML file  and display a friendly message to the user
 * @author Ibrabel <[email protected]>
 */
public class LogToFile {

    protected static final Logger logger=Logger.getLogger("MYLOG");
    /**
     * log Method 
     * enable to log all exceptions to a file and display user message on demand
     * @param ex
     * @param level
     * @param msg 
     */
    public static void log(Exception ex, String level, String msg){

        FileHandler fh = null;
        try {
            fh = new FileHandler("log.xml",true);
            logger.addHandler(fh);
            switch (level) {
                case "severe":
                    logger.log(Level.SEVERE, msg, ex);
                    if(!msg.equals(""))
                        JOptionPane.showMessageDialog(null,msg,
                            "Error", JOptionPane.ERROR_MESSAGE);
                    break;
                case "warning":
                    logger.log(Level.WARNING, msg, ex);
                    if(!msg.equals(""))
                        JOptionPane.showMessageDialog(null,msg,
                            "Warning", JOptionPane.WARNING_MESSAGE);
                    break;
                case "info":
                    logger.log(Level.INFO, msg, ex);
                    if(!msg.equals(""))
                        JOptionPane.showMessageDialog(null,msg,
                            "Info", JOptionPane.INFORMATION_MESSAGE);
                    break;
                case "config":
                    logger.log(Level.CONFIG, msg, ex);
                    break;
                case "fine":
                    logger.log(Level.FINE, msg, ex);
                    break;
                case "finer":
                    logger.log(Level.FINER, msg, ex);
                    break;
                case "finest":
                    logger.log(Level.FINEST, msg, ex);
                    break;
                default:
                    logger.log(Level.CONFIG, msg, ex);
                    break;
            }
        } catch (IOException | SecurityException ex1) {
            logger.log(Level.SEVERE, null, ex1);
        } finally{
            if(fh!=null)fh.close();
        }
    }

    public static void main(String[] args) {

        /*
            Create simple frame for the example
        */
        JFrame myFrame = new JFrame();
        myFrame.setTitle("LogToFileExample");
        myFrame.setSize(300, 100);
        myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        myFrame.setLocationRelativeTo(null);
        JPanel pan = new JPanel();
        JButton severe = new JButton("severe");
        pan.add(severe);
        JButton warning = new JButton("warning");
        pan.add(warning);
        JButton info = new JButton("info");
        pan.add(info);

        /*
            Create an exception on click to use the LogToFile class
        */
        severe.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent ae) {
                int j = 20, i = 0;
                try {
                    System.out.println(j/i);
                } catch (ArithmeticException ex) {
                    log(ex,"severe","You can't divide anything by zero");
                }

            }

        });

        warning.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent ae) {
                int j = 20, i = 0;
                try {
                    System.out.println(j/i);
                } catch (ArithmeticException ex) {
                    log(ex,"warning","You can't divide anything by zero");
                }

            }

        });

        info.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent ae) {
                int j = 20, i = 0;
                try {
                    System.out.println(j/i);
                } catch (ArithmeticException ex) {
                    log(ex,"info","You can't divide anything by zero");
                }

            }

        });

        /*
            Add the JPanel to the JFrame and set the JFrame visible
        */
        myFrame.setContentPane(pan);
        myFrame.setVisible(true);
    }
}
Ibrabel
fuente
4
import java.io.IOException;
import org.apache.log4j.Appender;
import org.apache.log4j.FileAppender;
import org.apache.log4j.Logger;
import org.apache.log4j.SimpleLayout;

/**
 * @author Kiran
 * 
 */
public class MyLogger {

    public MyLogger() {
    }

    public static void main(String[] args) {
        Logger logger = Logger.getLogger("MyLog");
        Appender fh = null;
        try {
            fh = new FileAppender(new SimpleLayout(), "MyLogFile.log");
            logger.addAppender(fh);
            fh.setLayout(new SimpleLayout());
            logger.info("My first log");
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        logger.info("Hi How r u?");
    }
}
kanaparthikiran
fuente
1
Gracias, esto me ayudó, pero Log4j 2 está saliendo ahora y tuve que buscar en el sitio para encontrar la versión 1.2.
SoluableNonagon el
3
int SIZE = "<intialize-here>"
int ROTATIONCOUNT = "<intialize-here>"

Handler handler = new FileHandler("test.log", SIZE, LOG_ROTATIONCOUNT);
logger.addHandler(handler);     // for your code.. 

// you can also set logging levels
Logger.getLogger(this.getClass().getName()).log(Level.[...]).addHandler(handler);
Aura
fuente
1

Espero que la gente encuentre esto útil

public static void writeLog(String info) {
    String filename = "activity.log";
    String FILENAME = "C:\\testing\\" + filename;
    BufferedWriter bw = null;
    FileWriter fw = null;
    try {
        fw = new FileWriter(FILENAME, true);
        bw = new BufferedWriter(fw);
        bw.write(info);
        bw.write("\n");
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (bw != null)
                bw.close();
            if (fw != null)
                fw.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}
Bases de nieve
fuente
1
sí, perdí media hora y mi ingenio tratando de hacer que log4j escriba en un archivo maldito. La mayoría de las herramientas son demasiado complicadas para el problema que están resolviendo.
Mihai Raulea
0

Aquí está mi clase de registro basada en la respuesta aceptada :

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.*;

public class ErrorLogger
{
    private Logger logger;

    public ErrorLogger()
    {
        logger = Logger.getAnonymousLogger();

        configure();
    }

    private void configure()
    {
        try
        {
            String logsDirectoryFolder = "logs";
            Files.createDirectories(Paths.get(logsDirectoryFolder));
            FileHandler fileHandler = new FileHandler(logsDirectoryFolder + File.separator + getCurrentTimeString() + ".log");
            logger.addHandler(fileHandler);
            SimpleFormatter formatter = new SimpleFormatter();
            fileHandler.setFormatter(formatter);
        } catch (IOException exception)
        {
            exception.printStackTrace();
        }

        addCloseHandlersShutdownHook();
    }

    private void addCloseHandlersShutdownHook()
    {
        Runtime.getRuntime().addShutdownHook(new Thread(() ->
        {
            // Close all handlers to get rid of empty .LCK files
            for (Handler handler : logger.getHandlers())
            {
                handler.close();
            }
        }));
    }

    private String getCurrentTimeString()
    {
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
        return dateFormat.format(new Date());
    }

    public void log(Exception exception)
    {
        logger.log(Level.SEVERE, "", exception);
    }
}
BullyWiiPlaza
fuente
0

Aquí hay un ejemplo de cómo sobrescribir la configuración de Logger del código. No requiere un archivo de configuración externo.

FileLoggerTest.java:

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;

public class FileLoggerTest {

    public static void main(String[] args) {

        try {
            String h = MyLogHandler.class.getCanonicalName();
            StringBuilder sb = new StringBuilder();
            sb.append(".level=ALL\n");
            sb.append("handlers=").append(h).append('\n');
            LogManager.getLogManager().readConfiguration(new ByteArrayInputStream(sb.toString().getBytes("UTF-8")));
        } catch (IOException | SecurityException ex) {
            // Do something about it
        }

        Logger.getGlobal().severe("Global SEVERE log entry");
        Logger.getLogger(FileLoggerTest.class.getName()).log(Level.SEVERE, "This is a SEVERE log entry");
        Logger.getLogger("SomeName").log(Level.WARNING, "This is a WARNING log entry");
        Logger.getLogger("AnotherName").log(Level.INFO, "This is an INFO log entry");
        Logger.getLogger("SameName").log(Level.CONFIG, "This is an CONFIG log entry");
        Logger.getLogger("SameName").log(Level.FINE, "This is an FINE log entry");
        Logger.getLogger("SameName").log(Level.FINEST, "This is an FINEST log entry");
        Logger.getLogger("SameName").log(Level.FINER, "This is an FINER log entry");
        Logger.getLogger("SameName").log(Level.ALL, "This is an ALL log entry");

    }
}

MyLogHandler.java

import java.io.IOException;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.SimpleFormatter;

public final class MyLogHandler extends FileHandler {

    public MyLogHandler() throws IOException, SecurityException {
        super("/tmp/path-to-log.log");
        setFormatter(new SimpleFormatter());
        setLevel(Level.ALL);
    }

    @Override
    public void publish(LogRecord record) {
        System.out.println("Some additional logic");
        super.publish(record);
    }

}
Andrew Krasny
fuente