如何根据包选择性地将system.out重定向到文件

时间:2015-08-28 15:10:07

标签: java redirect logging

我的java程序使用lib A. 我的java程序使用System.out.print()。而lib A也使用System.out.print()。 但我只希望控制台显示我的程序中system.out.print()的输出。不希望控制台显示来自lib A的日志。 怎么做? 感谢。

2 个答案:

答案 0 :(得分:1)

如果性能和可维护性不是问题,您可以通过创建在执行任何操作之前检查调用方的打印流来过滤现有的System.out流。下面是一些示例代码,但您必须覆盖每个方法来检查调用者:

 public class PackagePrintStream extends PrintStream {

    public PackagePrintStream(OutputStream out, boolean autoFlush, String encoding) throws UnsupportedEncodingException {
        super(out, autoFlush, encoding);
    }

    @Override
    public void println(Object x) {
        /**
         * You have to override all of the PrintStream methods
         * not just println.
         */
        if (allow()) {
            super.println(x); 
        }
    }

    private boolean allow() {
        String cn = inferCaller().getClassName();
        return !cn.startsWith("lib.A"); //@todo use the right package name.
    }

    private boolean isPrintImplFrame(String cname) {
        return PackagePrintStream.class.getName().equals(cname);
    }

    private StackTraceElement inferCaller() {
        StackTraceElement stack[] = (new Throwable()).getStackTrace();
        int ix = 0;
        while (ix < stack.length) {
            StackTraceElement frame = stack[ix];
            String cname = frame.getClassName();
            if (isPrintImplFrame(cname)) {
                break;
            }
            ix++;
        }

        while (ix < stack.length) {
            StackTraceElement frame = stack[ix];
            String cname = frame.getClassName();
            if (!isPrintImplFrame(cname)) {
                return frame;
            }
            ix++;
        }

        return new StackTraceElement(PackagePrintStream.class.getName(), "write",
                PackagePrintStream.class.getName(), -1);
    }
}

然后要安装流,请执行以下操作:

System.setOut(new PackagePrintStream(System.out, true, "UTF-8"));

答案 1 :(得分:0)

如果你只是尽量少用这些课程,你可以这样做:

您需要调用一个类,如下所示:

static class DontPrint {

    public void method() {
        System.out.println("Called from DontPrint.method()");
    }
}

在init期间创建一个logPrinter以便稍后使用。

 PrintStream logPrinter = new PrintStream(new File("dontprint.log"));

然后每当你调用它的方法时,你都可以使用setOut()来重定向。

System.out.println("first print from main");
PrintStream orig_out = System.out;

System.setOut(logPrinter);
new DontPrint().method();
System.setOut(orig_out);
System.out.println("second call from main");

当然,如果你必须这么做,那将非常不方便。您可以创建一个包装类来保持来回交换输出,或者如果可以的话,将其修复到库源中。日志框架允许为不同的类配置不同的输出级别和不同的输出文件,这将是一个更完整的解决方案。手动重定向更多是一种临时解决方法。