【问题标题】:Java + Eclipse: Synchronize stdout and stderrJava + Eclipse:同步标准输出和标准错误
【发布时间】:2011-02-23 05:23:59
【问题描述】:

我使用 Eclipse。当我有这样的应用程序时:

write 20 times 'Hello World\n' to stdout
write 'ERROR\n' to stderr
write 5 times 'Hello  World\n' to stdout

输出多次看起来像这样:

Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
...
Hello World
Hello World
Hello World
ERROR

有没有办法同步这两个输出流?当然,在 20 次 Hello World 的块后无需等待几毫秒,在打印 ERROR 后等待几毫秒。

【问题讨论】:

    标签: java eclipse synchronization stdio


    【解决方案1】:

    信不信由你,冲洗在这里不是解决方案......

    如果流导致“由底层操作系统提供的抽象”(例如磁盘驱动器或控制台),则剩余字节“将传递给操作系统进行写入;它不保证它们确实被写入.. .”(见the OutputStream documentation)。这里的关键是,如果操作系统愿意,它可以以不同的顺序处理来自不同流的刷新。

    我刚刚在我的程序中发生了这种情况。我在两条正常消息之间出现了一条错误消息,这两条消息在错误消息出现之前都已刷新。

    所以问题仍然存在, 有没有一种内置方法可以同步两个流?还是我们必须手动处理?

    【讨论】:

      【解决方案2】:

      对于“严肃”的使用,我不喜欢直接写信给System.out/System.err,因为它对目的地进行了硬编码,而且它还使用了相当古怪的PrintStream(它是字节流还是字符流?) .如果将输出流包装在自己的PrintWriter 中,则可以将其设置为自动刷新 - 构造函数中的第二个参数是auto-flush

      例如

      PrintWriter out = new PrintWriter(System.out, true);
      PrintWriter err = new PrintWriter(System.err, true);
      
      out.println("Hello world");
      //this will flush after writing the end of line
      

      【讨论】:

      • "是字节流还是字符流?".它显然是一个字节流。写入字符、字符串、数字等的方法使用 JVM 的默认字符集隐式转换为字节。
      • @Stephen 我说的是它在 java 中的客户端接口。 PrintWriter 允许写入字符,OutputStream 写入字节,但PrintStream 提供的接口同时写入字节和字符,但是正如您所指出的,如果您通过流写入字符串,那么您将从当前默认编码的另一端。这不是一件好事,是 i18n 完成之前的早期 jdk 1.0 设计的一个反常现象,i18n 带来了写字节和写字符的明显区别。有关更多信息,请参阅第二个链接。
      【解决方案3】:

      System.out 和 System.err 是普通的PrintStream 对象(它们提供了一个flush() 方法),所以试试System.out.flush()System.err.flush()

      【讨论】:

        【解决方案4】:

        AFAIK 没有可靠的方法来强制同步 2 个不相关的流。

        一种解决方法是只使用一个流:例​​如使用System.setErr() 重定向到 err,以便所有内容都打印在错误流上:

        System.setErr(System.out);
        

        或者反过来通过System.setOut()

        System.setOut(System.err);
        

        这样做的一个缺点是它可能会改变语法高亮:例如某些 IDE 可能会以不同方式突出显示 stderr 和 stdout 上的文本

        【讨论】:

          【解决方案5】:

          Thread.sleep(1) 之后添加一个刷新,99.9% 的输出顺序将是正确的。

          例如,这将按预期显示。

          System.out.println( "stdout 1" ); System.out.flush(); Thread.sleep( 1 );
          System.err.println( "stderr 1" ); System.err.flush(); Thread.sleep( 1 );
          System.out.println( "stdout 2" ); System.out.flush(); Thread.sleep( 1 );
          System.err.println( "stderr 2" ); System.err.flush(); Thread.sleep( 1 );
          

          唯一的缺点是睡眠时间为 1 毫秒,即 1/1000 秒

          【讨论】:

          • 这个可怕的解决方案确实有效。在 intellij 中,它更像是 sleep 1000 - 500 是不够的。适用于非生产/调试环境
          猜你喜欢
          • 2011-09-01
          • 2011-06-26
          • 1970-01-01
          • 2014-07-22
          • 2022-07-23
          • 1970-01-01
          • 2014-08-25
          • 1970-01-01
          相关资源
          最近更新 更多