Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/341.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么刷新流没有效果,而刷新写入程序却有效果_Java_Bufferedreader - Fatal编程技术网

Java 为什么刷新流没有效果,而刷新写入程序却有效果

Java 为什么刷新流没有效果,而刷新写入程序却有效果,java,bufferedreader,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());

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

客户:

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.
}
但是如果我们刷新流,就会抛出异常

服务器:

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.
}

这种差异的原因是什么?

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

当您刷新底层流时,这就是您所做的一切。
BufferedWriter
仍有其缓冲区。你绕过那些

然而,当您刷新
BufferedWriter
时,您会处理它的附加缓冲层,将它们发送到底层流。
BufferedWriter
flush()
实现之后也会调用底层流上的
flush()
,因此您会得到一个完整的[flush higher-level buffers to-baseding stream]=>[flush The-based stream]

您可以在(我的)注释中看到该行为:


如果您直接调用底层流的
flush()
,本质上就是跳过上述代码片段中的
BufferedWriter#flushBuffer()
调用。

OutputStream API可能会有所帮助

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

OutputStream的刷新方法不起任何作用。


和client.getOutputStream()获取SocketOutputStream,它扩展了FileOutputStream,并且没有覆盖刷新方法。

问题的一部分说刷新导致异常,但问题的另一部分说它没有效果。哪一个?有趣的是,如果我们刷新顶层缓冲区,底层会自动刷新,对吗?@St.Antario yes;很抱歉我意识到我忘记了那个细节,并在你发布的时候添加了它。这个可能也很有用:“刷新流。如果流保存了各种write()中的任何字符方法,将它们立即写入其预期目标。然后,如果该目标是另一个字符或字节流,则刷新它。因此,一次flush()调用将刷新写入器和输出流链中的所有缓冲区。”1
OutputStream#flush()
肯定会做一些事情:它保证在调用它之后,任何内部缓冲的数据都会被传递到操作系统进行写入,文档中明确指出了这一点。2.
SocketOutputStream
会覆盖
flush()
——它什么也不做,因为它不需要做,因为
write()
会为套接字做所有必要的工作(
SocketOutputStream
没有额外的缓冲)。因此,它仍然坚持该文档中描述的
OutputStream
不变量。在任何情况下,
SocketOutputStream
做什么都无关紧要,这不是观察到的问题。1.我同意第一点。2 SocketOutputStream不覆盖flush()当它扩展从OutputStream扩展的FileOutputStream时,也不会覆盖刷新方法;对不起,没有;但其余的#2保持不变
SocketOutputStream#flush()
不需要做任何事情(它仍然没有违反任何规定的规则),并且它不是OP描述的问题的一部分。注:OP的观察结果对于任何与
缓冲写入程序组合的底层流类型都是相同的;不管它是
SocketOutputStream