为什么刷新流没有任何效果,但冲刷作者有

时间:2014-11-14 06:24:07

标签: java bufferedreader

我有最简单的客户端 - 服务器通信。

客户端:

public static void main(String args[]) throws Exception{
    Socket s = new Socket("localhost", 12345);
    BufferedReader r = new BufferedReader(new InputStreamReader(s.getInputStream()));
    System.out.println(r.readLine());
    s.close();
}

服务器:

public static void main(String args[]) throws Exception{
    @SuppressWarnings("resource")
    ServerSocket server = new ServerSocket(12345);
    Socket client = server.accept();
    OutputStream out = client.getOutputStream();
    BufferedWriter w = new BufferedWriter(new PrintWriter(out));
    w.write("Hello client\n");
    w.flush(); //Works fine, client printed Hello client
}

但是如果我们刷新流,则会抛出异常。

服务器:

public static void main(String args[]) throws Exception{
    @SuppressWarnings("resource")
    ServerSocket server = new ServerSocket(12345);
    Socket client = server.accept();
    OutputStream out = client.getOutputStream();
    BufferedWriter w = new BufferedWriter(new PrintWriter(out));
    w.write("Hello client\n");
    out.flush(); //Has no effect, doesn't deliver the line to the client.
}

这种差异的原因是什么?

2 个答案:

答案 0 :(得分:2)

这是因为BufferedWriter在它独立包装的流的顶部添加了一层自己的缓冲。

当您刷新基础流时,您正在做的就是这些。 BufferedWriter仍有缓冲区。你绕过了那些。

但是,当您刷新BufferedWriter时,您需要处理其额外的缓冲层,然后将其发送到基础流。 BufferedWriter的{​​{1}}实现之后也会在基础流上调用flush(),因此您可以获得[将更高级别缓冲区刷新到基础流]的完整链[= 1]。 [刷新基础流]。

您可以在source for BufferedWriter#flush()(评论我的)中看到该行为:

flush()

如果您直接呼叫基础流public void flush() throws IOException { synchronized (lock) { flushBuffer(); // Flushes this BufferedWriters buffers to 'out'. out.flush(); // Now flushes 'out' (the stream it wraps). } } ,实际上您正在跳过上述代码段中的flush()来电。

答案 1 :(得分:0)

OutputStream API可能有帮助。

刷新此输出流并强制写出任何缓冲的输出字节。 flush的一般契约是调用它表示,如果先前写入的任何字节已被输出流的实现缓冲,则应立即将这些字节写入其预期目的地。 如果该流的预期目的地是由底层操作系统提供的抽象,例如文件,则刷新流仅保证先前写入流的字节被传递到操作系统以进行写入;它不能保证它们实际上写入物理设备,如磁盘驱动器。

OutputStream的flush方法不执行任何操作。

和client.getOutputStream()获取扩展FileOutputStream的SocketOutputStream,而不是覆盖flush mothod。