Java System.out.println和System.err.println出现故障

Java System.out.println和System.err.println出现故障,java,console,system,Java,Console,System,我的System.out.println()和System.err.println()调用没有按照我的顺序打印到控制台 public static void main(String[] args) { for (int i = 0; i < 5; i++) { System.out.println("out"); System.err.println("err"); } } 而不是交替执行out和err。这是为什么?它们是不同的流,在不同的

我的
System.out.println()
System.err.println()
调用没有按照我的顺序打印到控制台

public static void main(String[] args) {
    for (int i = 0; i < 5; i++) {
        System.out.println("out");
        System.err.println("err");
    }
}

而不是交替执行
out
err
。这是为什么?

它们是不同的流,在不同的时间冲洗

如果你把

System.out.flush();
System.err.flush();
在您的循环中,它将按预期工作

为了澄清这一点,输出流是缓存的,所以所有的写操作都会进入这个内存缓冲区。经过一段时间的安静之后,它们实际上被写出来了


您写入两个缓冲区,然后在一段时间不活动后,它们都被刷新(一个接一个)。

它们是不同的流,在不同的时间刷新

如果你把

System.out.flush();
System.err.flush();
在您的循环中,它将按预期工作

为了澄清这一点,输出流是缓存的,所以所有的写操作都会进入这个内存缓冲区。经过一段时间的安静之后,它们实际上被写出来了


您写入两个缓冲区,然后在一段时间不活动后,它们都被刷新(一个接一个)。

如果您使用Eclipse控制台,工作中似乎有两种不同的现象:
如所述,一种是JVM处理流的方式,另一种是Eclipse读取这些流的方式,如所述。因为我使用的是Eclipse,所以发布的优雅的
flush()
-解决方案(仅解决JVM问题)是不够的

最后我自己编写了一个名为
EclipseTools
的助手类,包含以下内容(以及所需的包声明和导入)。这有点像黑客,但解决了两个问题:

public class EclipseTools {

    private static List<OutputStream> streams = null;
    private static OutputStream lastStream = null;

    private static class FixedStream extends OutputStream {

        private final OutputStream target;

        public FixedStream(OutputStream originalStream) {
            target = originalStream;
            streams.add(this);
        }

        @Override
        public void write(int b) throws IOException {
            if (lastStream!=this) swap();
            target.write(b);
        }

        @Override
        public void write(byte[] b) throws IOException {
            if (lastStream!=this) swap();
            target.write(b);
        }

        @Override
        public void write(byte[] b, int off, int len) throws IOException {
            if (lastStream!=this) swap();
            target.write(b, off, len);
        }

        private void swap() throws IOException {
            if (lastStream!=null) {
                lastStream.flush();
                try { Thread.sleep(200); } catch (InterruptedException e) {}
            }
            lastStream = this;
        }

        @Override public void close() throws IOException { target.close(); }
        @Override public void flush() throws IOException { target.flush(); }
    }

    /**
     * Inserts a 200ms delay into the System.err or System.out OutputStreams
     * every time the output switches from one to the other. This prevents
     * the Eclipse console from showing the output of the two streams out of
     * order. This function only needs to be called once.
     */
    public static void fixConsole() {
        if (streams!=null) return;
        streams = new ArrayList<OutputStream>();
        System.setErr(new PrintStream(new FixedStream(System.err)));
        System.setOut(new PrintStream(new FixedStream(System.out)));
    }
}
公共类日食工具{
私有静态列表流=null;
私有静态OutputStream lastStream=null;
私有静态类FixedStream扩展OutputStream{
私有最终输出流目标;
公共固定流(OutputStream originalStream){
目标=原始流;
添加(此项);
}
@凌驾
公共无效写入(int b)引发IOException{
如果(lastStream!=此)交换();
目标。编写(b);
}
@凌驾
公共无效写入(字节[]b)引发IOException{
如果(lastStream!=此)交换();
目标。编写(b);
}
@凌驾
公共无效写入(字节[]b,int off,int len)引发IOException{
如果(lastStream!=此)交换();
目标。注销(b、注销、len);
}
私有void swap()引发IOException{
if(lastStream!=null){
lastStream.flush();
试试{Thread.sleep(200);}catch(InterruptedException e){}
}
lastStream=这个;
}
@重写公共void close()引发IOException{target.close();}
@重写公共void flush()引发IOException{target.flush();}
}
/**
*将200ms延迟插入System.err或System.out OutputStreams
*每次输出从一个切换到另一个时。这会防止
*Eclipse控制台不显示两个数据流的输出
*这个函数只需要调用一次。
*/
公共静态void fixConsole(){
如果(streams!=null)返回;
streams=新的ArrayList();
System.setErr(新的PrintStream(新的FixedStream(System.err));
系统放样(新打印流(新固定流(系统放样));
}
}
要使用,只需在代码开头调用一次
EclipseTools.fixConsole()

基本上,这将用一组自定义流取代两个流
System.err
System.out
,这些流只需将其数据转发到原始流,但要跟踪最后写入的流。如果写入的流发生更改,例如
System.err.something(…)
后跟
System.out.something(…)
,它将刷新最后一个流的输出,并等待200ms,以便Eclipse控制台有时间完成打印


注意:200ms只是一个粗略的初始值。如果此代码减少了,但没有为您消除问题,请将
Thread.sleep
中的延迟从200增加到更高的值,直到它正常工作。或者,如果此延迟有效但影响代码的性能(如果您经常交替流),您可以尝试逐渐减少延迟,直到出现错误。

如果您使用的是Eclipse控制台,则工作中似乎存在两种不同的现象:
一种,如所述,是JVM对流的处理,另一个是Eclipse读取这些流的方式,如所述。因为我使用的是Eclipse,所以发布的优雅的
flush()
-解决方案(仅解决JVM问题)是不够的

最后我自己编写了一个名为
EclipseTools
的助手类,包含以下内容(以及所需的包声明和导入)。这有点像黑客,但解决了两个问题:

public class EclipseTools {

    private static List<OutputStream> streams = null;
    private static OutputStream lastStream = null;

    private static class FixedStream extends OutputStream {

        private final OutputStream target;

        public FixedStream(OutputStream originalStream) {
            target = originalStream;
            streams.add(this);
        }

        @Override
        public void write(int b) throws IOException {
            if (lastStream!=this) swap();
            target.write(b);
        }

        @Override
        public void write(byte[] b) throws IOException {
            if (lastStream!=this) swap();
            target.write(b);
        }

        @Override
        public void write(byte[] b, int off, int len) throws IOException {
            if (lastStream!=this) swap();
            target.write(b, off, len);
        }

        private void swap() throws IOException {
            if (lastStream!=null) {
                lastStream.flush();
                try { Thread.sleep(200); } catch (InterruptedException e) {}
            }
            lastStream = this;
        }

        @Override public void close() throws IOException { target.close(); }
        @Override public void flush() throws IOException { target.flush(); }
    }

    /**
     * Inserts a 200ms delay into the System.err or System.out OutputStreams
     * every time the output switches from one to the other. This prevents
     * the Eclipse console from showing the output of the two streams out of
     * order. This function only needs to be called once.
     */
    public static void fixConsole() {
        if (streams!=null) return;
        streams = new ArrayList<OutputStream>();
        System.setErr(new PrintStream(new FixedStream(System.err)));
        System.setOut(new PrintStream(new FixedStream(System.out)));
    }
}
公共类日食工具{
私有静态列表流=null;
私有静态OutputStream lastStream=null;
私有静态类FixedStream扩展OutputStream{
私有最终输出流目标;
公共固定流(OutputStream originalStream){
目标=原始流;
添加(此项);
}
@凌驾
公共无效写入(int b)引发IOException{
如果(lastStream!=此)交换();
目标。编写(b);
}
@凌驾
公共无效写入(字节[]b)引发IOException{
如果(lastStream!=此)交换();
目标。编写(b);
}
@凌驾
公共无效写入(字节[]b,int off,int len)引发IOException{
如果(lastStream!=此)交换();
目标。注销(b、注销、len);
}
私有void swap()引发IOException{
if(lastStream!=null){
System.out.println("out");
System.out.flush();
System.err.println("err");
System.err.flush();
System.out.println("out");
System.out.flush();
System.err.println("err");
System.err.flush();
System.out.println("out");*
System.err.println("err");*
System.out.println("out");*
System.err.println("err");*
System.out.flush();
System.err.flush();
public class Test {
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            System.out.print("OUT ");
            System.err.print("ERR ");
        }
    }
}
OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR
OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR
OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR
OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR
OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR OUT ERR
ERR ERR ERR ERR ERR ERR ERR ERR ERR ERR OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT 
OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT ERR ERR ERR ERR ERR ERR ERR ERR ERR ERR
ERR ERR ERR ERR ERR ERR ERR ERR ERR ERR OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT 
ERR ERR ERR ERR ERR ERR ERR ERR ERR ERR OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT
OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT ERR ERR ERR ERR ERR ERR ERR ERR ERR ERR 
public class Test {
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            System.out.print("OUT ");
            System.err.print("ERR ");
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
OUT ERR ERR OUT ERR OUT OUT ERR OUT ERR ERR OUT OUT ERR ERR OUT OUT ERR OUT ERR
OUT ERR ERR OUT ERR OUT OUT ERR OUT ERR ERR OUT OUT ERR ERR OUT OUT ERR OUT ERR
ERR OUT ERR OUT OUT ERR ERR OUT OUT ERR ERR OUT OUT ERR OUT ERR ERR OUT ERR OUT 
ERR OUT OUT ERR ERR OUT OUT ERR ERR OUT ERR OUT OUT ERR ERR OUT ERR OUT OUT ERR
OUT ERR OUT ERR ERR OUT OUT ERR ERR OUT OUT ERR ERR OUT ERR OUT OUT ERR OUT ERR 
    for(int i = 0; i< 5; i++){
        try {
            Thread.sleep(100);
            System.out.print("OUT");
            Thread.sleep(100);
            System.err.print("ERR");
        }catch (InterruptedException ex){
            System.out.println(ex.getMessage());
        }
    }