将输出和错误消息打印到控制台

6
我想在控制台中打印输出和错误信息。但有时输出的顺序会改变,先打印错误消息然后再打印简单消息。有人能帮我理解为什么会出现这种情况吗? 输出的顺序大部分时间都是不一致的。我正在使用Eclipse IDE,下面是我得到的输出。 我尝试打印以下代码:
System.out.println("simple message");  
System.err.println("error message");  

期望的结果是这样的:

简单消息

错误消息

但实际结果是这样的:

错误消息

简单消息


可能是因为它们是两个不同的流。 - ave4496
5
可能是Java: System.out.println and System.err.println out of order的重复问题。 - Nicholas K
@user489872是正确的- https://dev59.com/Z3I-5IYBdhLWcg3wYnSQ#1883333 - xxxvodnikxxx
7个回答

3

System.out.println()和System.err.println()是不同的执行流。输出流被缓存,因此所有写入都进入此内存缓冲区。经过一段时间的静默,它们实际上会被写出。下面是一个for循环,它基本上再次显示了您的错误:

for(int x = 0; x <= 5; x++) {
    System.out.println("Out");
    System.err.println("Err");



}

为了"清空"流,请在每次循环中调用.flush():
for(int x = 0; x <= 5; x++) {
    System.out.println("Out");
    System.out.flush();
    System.err.println("Err");
    System.err.flush();


}

在这个for循环中,out消息和err消息会最初打印,但在每次flush时,您的out消息将首先打印,然后是err消息。输出将类似于:
OutErr
Out
Out
Out
Out
Out

Err
Err
Err
Err
Err

这是因为System.out和System.err在不同的流上执行。


2
即使在写入后刷新流,这些流也会被Eclipse中的不同线程读取,如果写入几乎同时发生,则可能会出现读取stderr的线程先于读取stdout的线程执行,即使对stdout的相应写入先发生。
自Java 1.5以来,有ProcessBuilder类,通过在启动期间将stderr重定向到stdout可以解决这个问题 - 但是Eclipse显示stderr输出的特性会因此而破坏。
您可以在https://bugs.eclipse.org/bugs/show_bug.cgi?id=32205中添加您的意见。

更新:合并标准输出和标准错误流的选项已经实施,详情请参见https://www.eclipse.org/eclipse/news/4.13/jdt.php#console-output-synchronization。 - Till Brychcy

0

由于它们是两个不同的执行流,它们独立执行。而且它们不在不同的块作用域中,因此close()没有被调用,也就不会调用flush()。然后它们处于同一级别。所以JVM在这里发挥主导作用,按他想要的方式执行这两个流。

因此,在每个流的末尾有意地调用flush()将帮助您重新掌握代码的驾驶座位。


我已经尝试在每个语句后调用flush(),但仍然得到相同的输出,这不是期望的输出。 - user10212105

0

如先前的答案所建议的,您可以使用System.setErr将输出流和错误流设置为相同的流。

System.setErr(System.out);

重新分配“标准”错误输出流。
但是这种设置并不建议在生产环境中用于真实的应用程序。

0
  • 请记住,这不仅取决于用户定义的顺序,也取决于接收应用程序。
  • 例如,如果Eclipse IDE有两个线程,一个用于接收错误流,另一个用于接收system.out流,则这些线程不在您的控制范围内,因此您可能会看到时间到时间的顺序更改。
  • 如果您不关心性能,那么可以在两次操作之间加入一些暂停。

System.out.println("Out");

Thread.sleep(50);

System.err.println("error");


0

试一下吧...

System.out.println("Out");

 System.out.flush();

 System.err.flush();

 System.err.println(" err ");

不,它没有起作用,错误消息先打印出来了。 - user10212105

0

正如Simeon Ikudabo所说,这个任务是不可能完成的!!但是为了最接近的尝试,请尝试这个。

static void print(PrintStream p, Object o) throws InterruptedException {
    Object lock = new Object();
    synchronized (lock) {

        Runnable r = new Runnable() {
            public void run() {
                synchronized (lock)
                {
                p.println(o);
                lock.notify();
                }
            }
        };
        new Thread(r).start();

        lock.wait();
    }

}

public static void main(String[] args) throws InterruptedException {

    for (int i = 0; i < 50; i++) {
        print(System.out, "out");
        print(System.err, "err");

    }}

你可能认为它是完美的,但仍然有一丝丝微小的机会失去比赛,并且这也不是保证。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接