Java自定义记录器问题

时间:2015-10-27 15:03:31

标签: java logging

我有一个自定义Logger类:

import java.io.OutputStream;
import java.io.PrintStream;

public class Logger extends PrintStream{

    public Logger(OutputStream outputStream) {
        super(outputStream);
        logHeader();
    }

    private void logHeader(){
        for (int i=0; i<20; i++) print("#");
        print("Program execution start: ");
        print(CalendarClock.getInitTimeStamp());
        for (int i=0; i<20; i++) print("#");
        println();
    }

    public void logFooter(){
        for (int i=0; i<=20; i++) print("#");
        print("Program execution stop: ");
        print(CalendarClock.getCurrentTimeStamp());
        for (int i=0; i<=20; i++) print("#");
        println("\n");
    }

    @Override
    public void print(String arg0) {
        super.print(arg0);
        if (this.out != System.out) System.out.print(arg0);
    }

    @Override
    public void println(String arg0) {
        super.println(arg0);
        if (this.out != System.out) System.out.println(arg0);
    }
}

这是我的main课程:

public class Main {
    @SuppressWarnings("resource")
    public static void main(String[] args){
        File logFile = new File("data/test.log");
        Logger logger;

        try{
            if (!logFile.exists()) logFile.createNewFile();
            logger = new Logger(new FileOutputStream(logFile, false));
        } catch (IOException e) {
            logger = new Logger(System.out);

        }                                   
        logger.println("Hello World.");
        logger.println("Foo Bar");          
        logger.logFooter();
        logger.close();

    }

}

首先,Eclipse会在logger = new Logger(System.out); catch(IOException e)内的Resource leak: 'logger' is not closed at this location处显示警告。我必须添加@SuppressWarnings("resource")才能让它消失。

其次,该程序将以下内容输出到控制台:

####################Program execution start: 2015-10-27 10:55:51####################Hello World.Hello World.
Foo BarFoo Bar
#####################Program execution stop: 2015-10-27 10:55:51#####################

当它正确记录到文件时:

####################Program execution start: 2015-10-27 10:55:51####################
Hello World.
Foo Bar
#####################Program execution stop: 2015-10-27 10:55:51#####################

最后,如果我运行以下代码:

public class Main {
    @SuppressWarnings("resource")
    public static void main(String[] args){
        File logFile = new File("data/test.log");
        Logger logger;

        try{
            throw new IOException("Threw the exception!");
            /*if (!logFile.exists()) logFile.createNewFile();
            logger = new Logger(new FileOutputStream(logFile, false));*/
        } catch (IOException e) {
            logger = new Logger(System.out);
            logger.println(e.getMessage());
        }           
        logger.println("Hello World.");
        logger.println("Foo Bar");
        logger.logFooter();
        logger.close();

    }

}

输出正确打印为:

####################Program execution start: 2015-10-27 10:59:18####################
Threw the exception!
Hello World.
Foo Bar
#####################Program execution stop: 2015-10-27 10:59:18#####################

显然,这一切似乎都超出了我的理解范围,对此行为的任何解释都将受到赞赏。

更新 我通过覆盖空参数println解决了标题末尾没有新行的问题:

@Override
public void println() {
    super.println();
    if (out != System.out) System.out.println();
}

现在第一个main的输出是:

####################Program execution start: 2015-10-27 11:15:30####################
Hello World.Hello World.
Foo BarFoo Bar
#####################Program execution stop: 2015-10-27 11:15:30#####################

1 个答案:

答案 0 :(得分:0)

我使用调试器查看代码执行的顺序,发现PrintStream类实现了prinln(arg0)作为对print(arg0)newline()的调用,这相当于println()。因此,每次在println(arg0)中调用Logger时,arg0都会打印到stdout两次,一次在print(arg0),一次在println(arg0)

为了克服我的问题,我将println(arg0)课程中Logger的实施更改为:

@Override
public void println(String arg0) {
    print(arg0);
    println();
}