So schreiben Sie Protokolle in eine Textdatei, wenn Sie java.util.logging.Logger verwenden

147

Ich habe eine Situation, in der ich alle von mir erstellten Protokolle in eine Textdatei schreiben möchte.

Wir verwenden die API java.util.logging.Logger, um die Protokolle zu generieren.

Ich habe es versucht:

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

Aber ich bekomme meine Logs immer noch nur auf der Konsole ...

Pankaj
quelle
2
Eine Reihe von Antworten schlägt vor, FileHandler zu verwenden, wie Sie es ursprünglich versucht haben. Eine Sache, die Sie beachten sollten (eine schmerzlich gelernte Lektion): FileHandler ist synchronisiert . In einer High-Multithread-Anwendung müssen Sie lediglich einen zu protokollierenden Objekt übergeben, dessen toString () -Methode eine synchronisierte Methode aufruft. Vorsicht vor FileHandler.
Tim Boudreau

Antworten:

238

Probieren Sie dieses Beispiel aus. Für mich geht das.

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

}

Erzeugt die Ausgabe in 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?

Bearbeiten:

Verwenden Sie zum Entfernen des Konsolenhandlers

logger.setUseParentHandlers(false);

da der ConsoleHandler beim übergeordneten Logger registriert ist, von dem alle Logger abgeleitet sind.

Sri Harsha Chilakapati
quelle
1
Es funktioniert für mich ... Aber ich bekomme auch Protokolle an der Konsole. Wie entferne ich sie von dort?
Pankaj
Könnten Sie mir bitte vorschlagen, was zu tun ist, wenn ich alle Protokolle behalten möchte? Bei diesem Ansatz wird meine Textdatei tatsächlich ersetzt, wenn ich meine Anwendung zum zweiten Mal ausführe.
Pankaj
1
Wie das geht ... Ich google es, aber ich habe so viele verwirrende Codes gefunden ... Könnten Sie bitte helfen ...
Pankaj
7
@bluemunch Sie können den alternativen Konstruktor von verwenden FileHandler(path, true), um das Protokoll an eine vorhandene Protokolldatei anzuhängen.
Sri Harsha Chilakapati
1
@Line Ja. In diesem Fall behalte ich normalerweise eine Dienstprogrammmethode zum Erstellen eines Protokollierers.
Sri Harsha Chilakapati
16

Erstens, wo haben Sie Ihren Logger definiert und von welcher Klasse \ Methode, die versucht hat, ihn aufzurufen? Es gibt ein Arbeitsbeispiel, frisch gebacken:

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
    }
}   

In Ihrem Code haben Sie vergessen, den Formatierer zu definieren. Wenn Sie einen einfachen benötigen, können Sie dies wie oben erwähnt tun. Es gibt jedoch eine andere Option. Sie können ihn selbst formatieren. Es gibt ein Beispiel (fügen Sie ihn einfach anstelle dieser Zeile fh ein .setFormatter (neuer SimpleFormatter ()) folgenden Code):

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

Oder jede andere Modifikation, was auch immer Sie möchten. Ich hoffe es hilft.

DenisD
quelle
9

Der Speicherort der Protokolldatei kann über die Datei logging.properties gesteuert werden. Und es kann als JVM-Parameter übergeben werden, z.java -Djava.util.logging.config.file=/scratch/user/config/logging.properties

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

Konfigurieren des Dateihandlers

Um Protokolle an eine Datei zu senden, fügen Sie FileHandler zur handlers-Eigenschaft in der Datei logging.properties hinzu. Dadurch wird die Dateiprotokollierung global aktiviert.

handlers= java.util.logging.FileHandler Konfigurieren Sie den Handler, indem Sie die folgenden Eigenschaften festlegen:

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 gibt den Speicherort und das Muster der Ausgabedatei an. Die Standardeinstellung ist Ihr Home-Verzeichnis.

java.util.logging.FileHandler.limit gibt in Bytes die maximale Menge an, die der Logger in eine Datei schreibt.

java.util.logging.FileHandler.count gibt an, wie viele Ausgabedateien durchlaufen werden sollen.

java.util.logging.FileHandler.formatter gibt die Formatierungsklasse java.util.logging an, die die Dateihandlerklasse zum Formatieren der Protokollnachrichten verwendet. SimpleFormatter schreibt kurze "lesbare" Zusammenfassungen von Protokolldatensätzen.


So weisen Sie Java an, diese Konfigurationsdatei anstelle von $ JDK_HOME / jre / lib / logging.properties zu verwenden:

java -Djava.util.logging.config.file=/scratch/user/config/logging.properties
Awanish Kumar
quelle
Tolle Antwort, soweit ich sehe, die einzige globale. Ich habe mich entschlossen, logging.properties im JDK selbst zu ändern (obwohl sie sich in Java 11 im Verzeichnis conf des Java-Installationsverzeichnisses befinden). Es ist erwähnenswert, dass der Standardspeicherort einer solchen Protokolldatei user.home / javaX.log ist (wobei user.home die Systemberechtigung ist und X die nächste Nummer in der Reihenfolge ist - für die erste ist es 0).
Linie
5

Eine gute Bibliothek namens log4j für Java .
Dies bietet zahlreiche Funktionen. Gehen Sie durch den Link und Sie werden Ihre Lösung finden.

Chintan Rathod
quelle
Es gibt bereits log4j2, aber es muss auf Projektebene konfiguriert werden
Pini Cheyni
5

Vielleicht ist es das, was du brauchst ...

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
quelle
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
quelle
1
Danke, das hat mir geholfen, aber Log4j 2 kommt jetzt heraus und ich musste auf der Website herumfischen, um die Version 1.2 zu finden.
SoluableNonagon
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
quelle
1

Hoffe, die Leute finden das hilfreich

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();
        }
    }
}
Schneebasen
quelle
1
Ja, ich habe eine halbe Stunde verloren und mein Verstand versucht, log4j dazu zu bringen, in eine verdammte Datei zu schreiben. Die meisten Tools sind viel zu kompliziert für das Problem, das sie lösen.
Mihai Raulea
0

Hier ist meine Protokollierungsklasse basierend auf der akzeptierten Antwort :

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
quelle
0

Hier ist ein Beispiel zum Überschreiben der Logger-Konfiguration aus dem Code. Benötigt keine externe Konfigurationsdatei.

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
quelle