Java 为什么即使在更换System.out后仍有输出?

Java 为什么即使在更换System.out后仍有输出?,java,io,console,Java,Io,Console,我正在使用scpsolver进行一个小的个人项目。库正在生成输出,我不想看到。事实上,我报告这是一个bug,只是想看看他们怎么说 没有公开的方法来禁用输出。GLPKSolver类试图禁用iTunes,但正如下面的一条评论所述,它也没有做任何事情 我尝试将System.out和System.err更改为空输出流,但这没有帮助,因为库显然能够以不同的方式打印到控制台我还是不明白这是怎么回事。 最后,我尝试使用了一个setHook()函数,但仍然失败了,如底部的输出所示。 我的解算课 public c

我正在使用scpsolver进行一个小的个人项目。库正在生成输出,我不想看到。事实上,我报告这是一个bug,只是想看看他们怎么说

没有公开的方法来禁用输出。GLPKSolver类试图禁用iTunes,但正如下面的一条评论所述,它也没有做任何事情

我尝试将
System.out
System.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;
    }
}
输出:

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
特别要注意的是,“Hello,world!”和“Hi,world!”都没有出现在输出中。这样做会抑制GLPK输出的一小部分。如果我删除所有
系统。*
重定向,这就是我得到的

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

有趣的是,输出在hello world之后…

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

禁用输出并不容易,除非本机库本身具有这样做的功能。我不熟悉scpsolver或它使用的库,但有时间我可以看看。在一般情况下,您可能需要创建一个新的本机库来关闭输出

更新:在探索了一点之后,我在底层本机库中看到:

    solver.enablePrints(false);  // turn this to "false" to prevent printouts
使用GLPKAPI的程序员可以通过调用glp_term_out来启用和禁用终端输出。钩子函数glp_term_hook可用于截取终端输出。还提供了更细粒度输出控制,但此处未介绍-请参阅GLPK API手册

因此,您需要做的就是确保调用这些函数。简单对吧?在中,我看到在关闭本机库的输出时:

    solver.enablePrints(false);  // turn this to "false" to prevent printouts
但是这个对C代码本机库的调用是因为禁用打印的代码被注释掉了。事实上,它所做的一切都会泄漏一点内存:

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);
}
还有另一种方法可以禁用输出,方法是在中的
GlpkSolver
对象上设置一个“钩子”,但按照编写代码的方式,您无法访问此对象


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

将代码作为文本而不是图像添加我只是搜索了该包名,下载了代码,并对文件进行了grep。是的,它在任何地方都使用
System.out.println
。实际上,这看起来有点像黑客的工作。您将其报告为bug可能是正确的,但最好与作者联系,询问他们是否愿意让他人修复代码。然后将所有这些行更改为日志记录语句。这可能是唯一的办法。或者只需在您的控制台上添加额外的行。您对
println
如何在
System.out
中进行更改有何想法?
static
块的目的是尽可能早地(即在加载类时)让系统进行更改,但是控制台上描述的问题和解决方案意味着他们要么用其他东西来解决问题,要么
println()
正在被黑客攻击。我还考虑尝试在一个新的java“实例”中运行代码,其输出流将。。。在别的地方。创建一个“新的本机库”的概念对我来说是一个完全的谜,我将考虑启动一个新的JVM来运行解算器是一个选项,但是您需要以某种方式解决传入参数和传出结果的问题。顺便说一句,我已经用一点调查的结果更新了答案。由于您迄今为止提供的所有帮助,对原始帖子进行了重大更改。你已经做了很多,我衷心感谢你。