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
。