【问题标题】:Do you need System.out.flush() before System.error.print("");你需要 System.out.flush() 之前 System.error.print("");
【发布时间】:2014-09-07 08:20:36
【问题描述】:

如果您使用System.err.print("There was an error..."); System.error.flush();,是否需要事先刷新System.out。我知道用System.out.print("bla");System.error.print("bla"); 编写会导致未刷新的流混淆。

我假设您只需要在知道没有 System.out.println();System.out.print("\n"); 时才需要这样做,因为 "\n" 会自动在 java.lang.System 中刷新,但我只是想确保.

另外,请不要在 cmets 中说“你为什么不直接测试它?”因为这有点难以测试,因为您基本上是靠运气来查看流是否没有正确刷新。

谢谢!

编辑

答案:

如果没有异常,我想就用Logger.getLogger(Your_Class.class.getName()).log(Level.WHATEVER, "message");吧。

-

如果你不相信我说 sout 和 serr 搞混了...

证明(我刚刚制作的课程):

package test;

/**
 *
 * @author dylnmc
 */
public class Test {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        for (int i = 0; i < 20; i++) {
            if (i % 2 == 0) {
                System.out.println(i);
            } else {
                System.err.println(i);
            }
        }
    }

}

输出:

run:
0
1
3
2
4
6
8
10
12
14
16
18
5
7
9
11
13
15
17
19
BUILD SUCCESSFUL (total time: 0 seconds)

如果您将 Test.java 转换为 jar 并运行 java -jar file/to/jar/Test.jar pause 则不会不匹配 - 正如某些人所说(因为这是大多数 ide 控制台中的问题)。

-

-

另外,我仍然不能让两个不同的流在 Netbeans ide 中刷新;他们仍然到处都是。

【问题讨论】:

  • “混杂”是什么意思?那么 stdout 和 stderr 会按照您在 Java 应用程序中写入它们的精确顺序出现在终端上吗? 行为也会受到其他因素的影响,例如,IDE 控制台的行为可能与系统控制台不同。
  • 您使用这些 sysout 和 syserr 打印做什么?将这段代码集中在一个位置是否更有意义,以便在一个地方进行flush()?如果这是用于日志记录,请考虑使用日志记录框架而不是重新发明轮子,例如java.util.logging.
  • 打印出错误而不抛出异常
  • 本质上,我正在写一堆文件,如果我无法写入特定文件,我System.err.println("Could not write to file " + file.getAbsolutePath()); System.error.flush() 并继续尝试写入其他文件。
  • 有没有更好的方法来实现这一点?

标签: java system flush autoflush


【解决方案1】:

System.outSystem.err 是两个不同的数据流。写入一个通常不会改变另一个。像 Netbeans 或 Eclipse 这样的 IDE 会同时读取和读取错误流,并同时在控制台窗口中显示两者。从错误流中读取的数据可能会以红色突出显示。这使得输出看起来是“混合的”。

因此,System.out.flush() 不会对 System.err 产生任何影响。相反,您可以考虑使用System.setOut、System.setErr 将 System.out 重定向到单独的流,并在退出程序之前打印捕获的数据。

【讨论】:

  • Nooooooooo... 它们都是输出流,您必须刷新输出流,否则它们会变得混乱。出于同样的原因,当 BufferedWriter 或 FileWriter(或任何类型的写入器)已写入文本文件且未显式(或使用 reader.close() 隐式刷新)时,您无法使用 BufferedReader 或 FileReader 读取文件,您不能简单地混合 System.out.print() 和 System.err.print()。这就是我一遍又一遍地阅读的内容。也许我错了。 ?
  • @dylnmc 读取/写入单个文件的情况不同 - 它包括共享资源。但是stdout和stderr是两个不同的渠道
  • 我相信这就是你必须冲洗的原因。我以前见过这种做法。如果你只是简单地使用 sout 和 serr willy nilly 而没有 flush,那么它们就会混淆。
【解决方案2】:

System.out.println(String s) 和 System.err.println(String s) 不是原子操作,因为它们首先打印字符串,然后是换行符。原子性是相对的。这两个操作(打印字符串和打印换行符)在一个同步块中,因此从 Java 代码的角度来看它们是原子的。但是,对于底层系统,它们仍然是两个独立的操作。所以,如果控制台被err和out共享,代码如下:

System.out.println("abc");
System.out.println("def");

最终会导致“abc”、“\n”、“def”、“\n”以可能不正确的顺序打印。第一个换行符总是在“abc”之后打印,第二个换行符总是在“def”之后打印(由于同步)但是序列“abc”,“def”,“\n”,“\n”是可能的.

为避免这种情况,请避免使用 println:

System.out.print("abc" + "\n");
System.out.print("def" + "\n");

(当然,您应该为您的系统使用正确的行分隔符。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-18
    • 2020-11-03
    • 2011-12-14
    • 2015-03-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多