揭开Java IO流中的flush()的神秘面纱
2016-09-18 22:47
183 查看
前言:
大家在使用Java IO流中OutputStream、PrintWriter ……时,会经常用到它的flush()方法。
一.为什么要flush:
与在网络硬件中缓存一样,流还可以在软件中得到缓存,即直接在Java代码中缓存。这可以通过BufferedOutputStream或BufferedWriter 链接到底层流上来实现。因此,在写
完数据时,flush就显得尤为重要。
例如:
![](http://www.bdqn.cn/upload/2013/11/29/13856966211150.jpeg)
上图中WEB服务器通过输出流向客户端响应了一个300字节的信息,但是,这时的输出流有一个1024字节的缓冲区。所以,输出流就一直等着WEB服务器继续向客户端响应信 息,当WEB服务器的响应信息把输出流中的缓冲区填满时,这时,输出流才向WEB客户端响应消息。
为了解决这种尴尬的局面,flush()方法出现了。flush()方法可以强迫输出流(或缓冲的流)发送数据,即使此时缓冲区还没有填满,以此来打破这种死锁的状态。
当我们使用输出流发送数据时,当数据不能填满输出流的缓冲区时,这时,数据就会被存储在输出流的缓冲区中。如果,我们这个时候调用关闭(close)输出流,存储在输出流的缓冲区中的数据就会丢失。所以说,关闭(close)输出流时,应先刷新(flush)换冲的输出流,话句话说就是:“迫使所有缓冲的输出数据被写出到底层输出流中”。
二.解读flush()源码:
下面以BufferedOutputStream类为例:
看到这里大家明白了吧,其实flush()也是通过out.write()将数据写入底层输出流的。
======================================================================================
最近使用java的FileOutputStream写文件,调用到了flush()方法。
在Code Review时,同事指出没有调用flush()的必要。
于是查看了FileInputStream类的源代码,发现flush()其实是继承于其父类OutputStream的。
而OutputStream类的flush()却什么也没做,恍然大悟,真是“看源代码者得真相啊”。
其实flush()是Flushable接口的方法,官方文档的对该方法的注释是“Flushes this output stream and forces
any buffered output bytes to be written out.”。
OutputStream方法实现了Flushable接口,而又什么也没做,真是让人一头雾水,于是就出现了我的误解。
那么什么时候flush()才有效呢?
答案是:当OutputStream是BufferedOutputStream时。
当写文件需要flush()的效果时,需要
也就是说,需要将FileOutputStream作为BufferedOutputStream构造函数的参数传入,然后对BufferedOutputStream进行写入操作,才能利用缓冲及flush()。
查看BufferedOutputStream的源代码,发现所谓的buffer其实就是一个byte[]。
BufferedOutputStream的每一次write其实是将内容写入byte[],当buffer容量到达上限时,会触发真正的磁盘写入。
而另一种触发磁盘写入的办法就是调用flush()了。
google了一下,发现有这个误解的人不在少数,今天特以此文记之。
大家在使用Java IO流中OutputStream、PrintWriter ……时,会经常用到它的flush()方法。
一.为什么要flush:
与在网络硬件中缓存一样,流还可以在软件中得到缓存,即直接在Java代码中缓存。这可以通过BufferedOutputStream或BufferedWriter 链接到底层流上来实现。因此,在写
完数据时,flush就显得尤为重要。
例如:
![](http://www.bdqn.cn/upload/2013/11/29/13856966211150.jpeg)
上图中WEB服务器通过输出流向客户端响应了一个300字节的信息,但是,这时的输出流有一个1024字节的缓冲区。所以,输出流就一直等着WEB服务器继续向客户端响应信 息,当WEB服务器的响应信息把输出流中的缓冲区填满时,这时,输出流才向WEB客户端响应消息。
为了解决这种尴尬的局面,flush()方法出现了。flush()方法可以强迫输出流(或缓冲的流)发送数据,即使此时缓冲区还没有填满,以此来打破这种死锁的状态。
当我们使用输出流发送数据时,当数据不能填满输出流的缓冲区时,这时,数据就会被存储在输出流的缓冲区中。如果,我们这个时候调用关闭(close)输出流,存储在输出流的缓冲区中的数据就会丢失。所以说,关闭(close)输出流时,应先刷新(flush)换冲的输出流,话句话说就是:“迫使所有缓冲的输出数据被写出到底层输出流中”。
二.解读flush()源码:
下面以BufferedOutputStream类为例:
======================================================================================
最近使用java的FileOutputStream写文件,调用到了flush()方法。
在Code Review时,同事指出没有调用flush()的必要。
于是查看了FileInputStream类的源代码,发现flush()其实是继承于其父类OutputStream的。
而OutputStream类的flush()却什么也没做,恍然大悟,真是“看源代码者得真相啊”。
其实flush()是Flushable接口的方法,官方文档的对该方法的注释是“Flushes this output stream and forces
any buffered output bytes to be written out.”。
OutputStream方法实现了Flushable接口,而又什么也没做,真是让人一头雾水,于是就出现了我的误解。
那么什么时候flush()才有效呢?
答案是:当OutputStream是BufferedOutputStream时。
当写文件需要flush()的效果时,需要
FileOutputStream fos = new FileOutputStream("c:\a.txt"); BufferedOutputStream bos = new BufferedOutputStream(fos);
也就是说,需要将FileOutputStream作为BufferedOutputStream构造函数的参数传入,然后对BufferedOutputStream进行写入操作,才能利用缓冲及flush()。
查看BufferedOutputStream的源代码,发现所谓的buffer其实就是一个byte[]。
BufferedOutputStream的每一次write其实是将内容写入byte[],当buffer容量到达上限时,会触发真正的磁盘写入。
而另一种触发磁盘写入的办法就是调用flush()了。
google了一下,发现有这个误解的人不在少数,今天特以此文记之。
相关文章推荐
- 通过Response.Flush()实现下载失败的解决方法
- 高性能WEB开发 flush让页面分块,逐步呈现 flush让页面分块,逐步呈现
- php ob_flush,flush在ie中缓冲无效的解决方法
- Java BufferedWriter BufferedReader 源码分析
- 深入理解ob_flush和flush的区别(ob_flush()与flush()使用方法)
- php中flush()、ob_flush()、ob_end_flush()的区别介绍
- 深入理解Hibernate中的flush机制
- PHP flush()与ob_flush()的区别详解
- php中ob_flush函数和flush函数用法分析
- PHP flush 函数使用注意事项
- Java中BufferedReader与BufferedWriter类的使用示例
- 简单谈谈php中ob_flush和flush的区别
- MySQL忘记密码的时候初始化密码的最佳方法
- wkhtmtopdf--高分辨率转HTML成PDF(一)
- wkhtmtopdf--高分辨率转HTML成PDF(二)
- MySQL的FLUSH句法和作用
- mysql: Host * is blocked because of many connection errors
- mysql 之flush操作
- 黑马程序员_I/O流总结
- IO流