为什么即使更改System.out也有输出?

时间:2020-08-10 04:19:00

标签: java io console

我正在使用scpsolver进行一个个人项目。该库正在生成输出,我不想看到。我实际上将其报告为错误,只是为了看看他们对此有何评论。

没有禁用输出的公开方法。 GLPKSolver类尝试使用GLPK暴露给他们的东西禁用它,但是正如下面的评论之一所述,它也不做任何事情。

我试图将System.outSystem.err更改为空输出流,但这没有帮助,因为该库显然能够以其他方式打印到控制台。 我还是不明白它是如何工作的。

最后,我尝试使用一个setHook()函数,但即使失败了,如底部的输出所示。 我的求解器课程

public class Solver {

    private static final PrintStream out = System.out;
    private static final PrintStream err = System.err;
    private static final PrintStream null_stream = new PrintStream( OutputStream.nullOutputStream() );

    static {
        System.setOut( null_stream );
        System.setErr( null_stream );
    }

    public static double[] solve ( double[][] A, double[] b, double[] c, double[] lb ) {

        LinearProgram lp = new LinearProgram( c );
        for ( int i = 0; i < b.length; i++ ) {
            lp.addConstraint( new LinearEqualsConstraint( A[i], b[i], "c" + i ) );
        }
        lp.setLowerbound( lb );
        lp.setMinProblem( false );
        LinearProgramSolver solver = SolverFactory.newDefault();

        double[] sol = solver.solve( lp );

        System.out.flush();
        System.err.flush();
        System.setOut( out );
        System.setErr( err );

        return sol;
    }
}

我重新编译的GLPKSolver.java中的代码片段重新插入库中

    solver.enablePrints(false);  // turn this to "false" to prevent printouts
    System.out.println("Hello, world!");
    solver.setHook( new GlpkHookIFC() {
        @Override
        public void fault ( String s ) {}
        @Override
        public void print ( String s ) {}
    } );
    System.out.println("Hi, world!");

输出:

GLPK Simplex Optimizer, v4.65
8 rows, 9 columns, 20 non-zeros
      0: obj = -0.000000000e+000 inf =  1.590e+002 (2)
      5: obj = -2.400000000e+003 inf =  0.000e+000 (0)
OPTIMAL LP SOLUTION FOUND

Process finished with exit code 0

尤其要注意“你好,世界!”和“嗨,世界!”都没有输出。这样做可以抑制GLPK输出的一小部分。如果我删除所有的System.*重定向,这就是我所得到的。

Hello, world!
Hi, world!
GLPK Simplex Optimizer, v4.65
8 rows, 9 columns, 20 non-zeros
      0: obj = -0.000000000e+000 inf =  1.590e+002 (2)
      5: obj = -2.400000000e+003 inf =  0.000e+000 (0)
OPTIMAL LP SOLUTION FOUND
x1: 2.0
x2: 0.0
x3: 0.5
x4: 0.0
x5: 4.9
x6: 2.2
x7: 0.0
x8: 0.0
x9: 2.4

有趣的是,输出出现在 问候世界之后。

1 个答案:

答案 0 :(得分:1)

您看到的输出是由scpsolver调用的本机库产生的。本机库可以直接写入JVM的标准输出流,而无需通过System.out和System.err对象,并且经常这样做是因为使用本机代码中的这些对象非常不方便。

禁用输出不是一件容易的事,除非本机库本身包含执行此操作的功能。我对scpsolver或它使用的库不熟悉,但是有空的时候我可以看看。在一般情况下,您可能需要创建一个新的本机库以关闭输出。

更新:经过一番摸索,我在基础本机库中看到了there is a way to turn off terminal output

使用GLPK API的程序员可以通过调用glp_term_out启用和禁用终端输出。挂钩函数glp_term_hook可用于拦截终端输出。还提供了更精细的谷物输出控制,但此处未涵盖-请查阅GLPK API手册。

因此,您要做的就是确保调用了这些函数。简单吧?在SCPSolver source code中,我看到there is an attempt关闭了本地库的输出:

    solver.enablePrints(false);  // turn this to "false" to prevent printouts

但是对C代码本机库doesn't actually do anything的此调用是因为注释了禁用打印的代码。实际上,它所做的所有事情都会泄漏一点内存:

JNIEXPORT void JNICALL
Java_org_gnu_glpk_GlpkSolver_enablePrints(JNIEnv *env, jobject obj,
                                          jboolean enable)
{
    info_t  *info=malloc(sizeof(info_t));

    info->env = env;
    info->obj = obj;

    //lib_set_fault_hook((void*)info, enable ? NULL : &_fault_hook_fn);
    //lib_set_print_hook((void*)info, enable ? NULL : &_print_hook_fn);
}

可以通过在scpsolver.lpsolver.GLPKSolverGlpkSolver solver对象上设置一个“ hook”来禁用输出,但是通过编写代码的方式,您无法访问该对象

我建议将scpsolver.lpsolver.GLPKSolver的代码复制到您自己的项目中的类中,并将对solver.enablePrints的调用替换为对solver.setHook的调用。