无意中发现了一个巨牛的人工智能教程,忍不住分享一下给大家。教程不仅是零基础,通俗易懂,而且非常风趣幽默,像看小说一样!觉得太牛了,所以分享给大家。点 这里 可以跳转到教程。

内容概要

Java IO 流的设计不得不让人拍案叫绝,佩服设计者鬼斧天工的手法。

如果你是 Java 初学者,我敢保证第一次接触 Java 的 IO 类,一定会 ”狂晕!”,倒不是因为它有多么难学而是太多让人难以琢磨,让人有种 “不识庐山真面目” 的感觉,当你用心学完之后也会收获 “只缘身在此山中” 的顿悟。

在 Java 编程的日子中尤其是在网络编程中,几乎离不开 Java 的 IO 流,所以学好和用好它是很有必要的。

关于 Java 的 IO 流的分类,可以去找找相关的资料,今天跟大家分享一下其中比较神奇的 flush 方法。

flush 与 OutputStream

该类实现了 Flushable 接口,所以重写了 flush 方法,看看 flush() 源码,会更加的让你明白:

 public void flush() throws IOException { } 

sorry,该实现为空。这里的 flush 居然是一个空方法,什么也没做。看清楚啊,该方法不是抽象方法,是一个实实在在的方法。除了方法体中一无所有,其它还好!看JDK的API如何解释吧!

flush public void flush() throws IOException 刷新此输出流并强制写出所有缓冲的输出字节。flush 的常规协定是:如果此输出流的实现已经缓冲了以前写入的任何字节,则调用此方法指示应将这些字节立即写入它们预期的目标。 如果此流的预期目标是由基础操作系统提供的一个抽象(如一个文件),则刷新此流只能保证将以前写入到流的字节传递给操作系统进行写入,但不保证能将这些字节实际写入到物理设备(如磁盘驱动器)。OutputStream 的 flush 方法不执行任何操作。指定者: 接口 Flushable 中的 flush 抛出: IOException - 如果发生 I/O 错误。  

开始,我安慰自己,该类是一个抽象类,它的子类肯定重写了该方法。

好吧,OutputStream 的直接子类有:ByteArrayOutputStreamFileOutputStreamFilterOutputStreamObjectOutputStreamOutputStreamPipedOutputStream 等几个类。

注意:这里的子类 OutputStream 是包 org.omg.CORBA.portable 的。

对于 FileOutputStreamByteArrayOutputStreamorg.omg.CORBA.portable.OutputStream 类它们的 flush() 方法均是从父类继承的 flush 方法。

FilterOutputStream 类重写了 flush() 方法,但是实质还是调用父类的 flush() 方法。ObjectOutputStreamPipedOutputStream 类重写了 flush() 方法。

JDK 中,有两大类IO流即字节流和字符流(包括输入和输出),这些流类中有些是带有缓冲区功能的有些是没有的。BufferedInputStream 和 BufferedOutputStream 是字节缓冲区类;BufferedReader 和 BufferedWriter 是字符缓冲区类

来举两个小例子,第一个例子主要是使用非缓冲区的IO流向文本中写入指定的字符串,第二个例子是使用带有缓冲区的IO流向文本中写入一定的字节数据。

1、例子1:向文本中写入字符串

 import java.io.BufferedOutputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream;​public class Test {     public static void main(String[] args) throws Exception {       File file = new File("text1.txt");       if (!file.exists()) {       file.createNewFile();       }       FileOutputStream fos = new FileOutputStream(file);DataOutputStream dos = new DataOutputStream(fos);dos.writeBytes("java io");} } 

这段代执行后,会在当前目录下产生 1KB 的文件(内容为 java io)。

特别注意,这里没有调用 flush 方法,只是调用了 writeBytes 方法。调用流程图如下:

2、例子2:向文本中写入一定字节的数据

 import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; ​public class Test {     public static void main(String[] args) throws Exception {       File file = new File("text2.txt");       if (!file.exists()) {           file.createNewFile();       }       FileOutputStream fos = new FileOutputStream(file);      BufferedOutputStream bos = new BufferedOutputStream(fos);       byte[] b = new byte[1024*8];        bos.write(b);       bos.flush();    }}  

这段代执行后,会在当前目录下产生 8KB 字节的文件。调用关系如下:

现在我们修改第二个例子的代码,主要修改两个地方

(1)、注释掉调用 flush() 方法;

(2)、将 byte 大小改为 1024 大小。

修改如下:

 import java.io.BufferedOutputStream;import java.io.File;import java.io.FileOutputStream;​public class Test {public static void main(String[] args) throws Exception {File file = new File("text.txt");if (!file.exists()) {file.createNewFile();}FileOutputStream fos = new FileOutputStream(file);BufferedOutputStream bos = new BufferedOutputStream(fos);byte[] b = new byte[1024];bos.write(b);//bos.flush();}}  

OK,再次运行代码,额的神啊???文件大小居然是0字节。

Why?

仔细的你会发现,第一个例子中的代码中并没有调用 flush() 方法,居然可以正常的写入。为什么第二个就不可以呢?还是从源码入手找答案吧!

DataOutputStream 继承 FilterOutputStream ,实现了 DataOutput 接口。我们知道 FilterOutputStream  类重写了 flush() 方法,但是实质还是调用父类的 flush() 方法。

DataOutputStream 类的 flush() 方法效仿其父类 FilterOutputStream 的做法,如下:

 public void flush() throws IOException {    out.flush(); }

即使你在第一个例子的代码后面加上 dos.flush() 结果也是正常的,加与不加是一样的效果,因为它们的父类 flush() 方法均为空,这就是为什么第一个代码的神奇所在。

第一个例子调用的 write 方法本质是调用了 native 实现的 wirte 方法,该方法直接将数据写入到了文件当中不需要调用 flush 方法,有兴趣的可以去查看一下 JDK 中的源码。

再看看第二个代码的 “病因” 在哪里?先看看 BufferedOutputStream 类的结构:

 public class BufferedOutputStream extends FilterOutputStream

再看看,它的 flush() 方法:

 public synchronized void flush() throws IOException {         flushBuffer(); out.flush();} ​/** Flush the internal buffer */    private void flushBuffer() throws IOException {   if (count > 0) {        out.write(buf, 0, count);       count = 0;        }    } 

不错,该类重写了 flush() 方法,不像前面几个类那样不是继承就是山寨父类的 flush() 方法。BufferedOutputStream 类是一个使用了缓冲技术的类,这种类一把都会自己实现 flush() 方法。

那么,有人会问使用这种类的时候,难道必须使用 flush() 方法吗,当然不是喽??!!有两种情况下可以不用调用 flush 方法。

(1)、写入的数据不小于8KB。

如下示例代码,byte 大小改为 8KB:

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream; public class Test {    public static void main(String[] args) throws Exception {   File file = new File("text.txt");        if (!file.exists()) {   file.createNewFile();   }       FileOutputStream fos = new FileOutputStream(file);         BufferedOutputStream bos = new BufferedOutputStream(fos);      byte[] b = new byte[1024*8];   bos.write(b);       //bos.flush(); }
}

执行代码,会产生 8KB 大小的文本文件。

(2)、修改默认缓冲区大小

如下示例代码,修改一下构造 BufferedOutputStream 的方法,设置默认缓冲区大小为 1024。

File file = new File("text4.txt");
if (!file.exists()) {file.createNewFile();
}
FileOutputStream fos = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(fos, 1024);
byte[] b = new byte[1024];
bos.write(b);
//bos.flush();

执行代码,会产生 1KB 大小的文本文件。

这里提醒一下,如果你的文件读写没有达到预期目的,十之八九是因为你没有调用 flush() 或者 close() 方法。

另外,字符流类大多数都实现了 flush() 或者 close() 方法,只不过,它们调用的是 StreamEncoder 类的该方法。该类位于 sun.nio.cs 包下面,其源码在我们JDK中是没有的。

可以点击 StreamEncoder.java 查看源码。

flush 与 Writer

该类 Writer 是一个抽象类,声明如下:

public abstract class Writer implements Appendable, Closeable, Flushable

Writer 类的 flush() 方法是一个抽象方法,其子类一般都实现了该方法。

所以,一般使用字符流之后需要调用一下 flush() 或者 close() 方法。

abstract public void flush() throws IOException;

细节请看JDK的API,或者Java的源码以及上面的 StreamEncoder 类源码。

今天就说到这里吧,本文主要借助Java IO中字节流与字符流的 flush() 方法,来说明学编程语言看源码和思考是很重要的。

总之,不管你使用哪种流(字符、字节、具有缓冲的流)技术,不妨调用一下 flush() 或者 close() 方法,防止数据无法写到输出流中。


学习没有一蹴而就的方法,坚持思考、练习才是王道~

Java基础:IO 流中的 flush相关推荐

  1. 黑马程序员-JAVA基础-IO流中的装饰设计模式

    ------- android培训.java培训.期待与您交流!------- 装饰设计模式: 当想要对已有的对象进行功能增强时,可以定义类,将已有的对象传入,基于已有的功能,并提供加强功能.那么,自 ...

  2. Java基础IO流(二)字节流小案例

    JAVA基础IO流(一)https://www.cnblogs.com/deepSleeping/p/9693601.html ①读取指定文件内容,按照16进制输出到控制台 其中,Integer.to ...

  3. # Java基础——IO流

    Java基础--IO流 File类的使用(熟悉构造器和方法的使用) File类的一个对象,代表一个文件或一个文件目录(俗称:文件夹) File类的声明在java.io包下 文件和文件目录路径的抽象表示 ...

  4. Java基础IO流之字符流的使用

    ☆引言☆ 大家好,我是痛而不言笑而不语的浅伤.IO流分为字节流和字符流,而上一篇文章我们学习了字节流(Java基础IO流之字符流的使用),这篇文章带大家一起来学习字符流吧.对文章中描述错误的希望大家积 ...

  5. Java基础-IO流对象之数据流(DataOutputStream与DataInputStream)

    Java基础-IO流对象之数据流(DataOutputStream与DataInputStream) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.数据流特点 操作基本数据类型 ...

  6. 黑马程序员-JAVA基础-IO流之字符流和字符流缓冲区

    ------- android培训.java培训.期待与您交流!------- Java 的IO 流 是实现输入和输出的基础,Java 中把不同的输入.输出源抽象表述为"流" (S ...

  7. java基础 io流 字节流 字符流 节点流 包装流 转换流 缓冲流 对象流 打印流 Properties类

    目录 1.概念 2.常用的文件操作 2.1 创建文件 2.2 获取文件相关信息 2.3 目录的操作和文件删除 3. IO流原理及流的分类 3.1 流的分类 4.InputStream 字节输入流 4. ...

  8. java基础 IO流

    目录 IO流简述: 整体框架: FileInputStream 为了在使用字节输入流读取中文内容输出不乱码,可以考虑: FileOutputStream Reader FileReader Buffe ...

  9. java基础—IO流——将一些字符写入到指定硬盘上的目录中去:

    将一些字符写入到指定硬盘上的目录中去: import java.io.*; //将一些文字储存到硬盘的文件中去 //操作的是文字,因此选用字符流来操作 public class FileWriterD ...

最新文章

  1. Linux 下 Oracle 内核参数优化
  2. 计算机网络概述的功能 组成,计算机网络的概述
  3. 基于Java的在线音乐网站的设计_基于javaweb的音乐网站的设计与实现论文.doc
  4. 西威变频器使用说明书_西威变频器调试说明.doc
  5. windows server 2008下载及序列号
  6. linux系统刷机教程,在 Linux 刷 BIOS
  7. soap python_Zeep: Python SOAP 客户端
  8. win10系统电脑分辨率异常解决办法
  9. Android/ios/h5 三步调起QQ群聊,一键加群
  10. 联想 缺少计算机所需的介质驱动程序,u盘安装win10显示缺少介质驱动最佳解决方法...
  11. 儿童摄影html代码源,HTML5织梦dede儿童摄影/影楼/写真/摄影工作室网站模板
  12. BitBucket介绍以及基础使用
  13. 无条件呼叫前转接已启用
  14. 大战略游戏:统治者:罗马 for Mac
  15. 利用python炒股talib_【手把手教你】股市技术分析利器之TA-Lib(一)
  16. 【HDU 5765】Bonds(进制运算妙用)
  17. Java后端学习,推荐书籍和学习路线
  18. CodeCombat计算机科学6.14脆弱的迷宫
  19. 【明解C语言】选择语句之switch
  20. python爬取微信公众号_python使用webdriver爬取微信公众号

热门文章

  1. Oracle安装与配置(Linux)
  2. 苏州新导室内定位方案之WIFI RTLS室内定位解决方案
  3. 理解电脑上的串口对应的端口号(com口)
  4. 正向代理和反向代理定义和区别
  5. 如何调整Thinkpad x230的mini DP输出分辨率?
  6. Java常用设计模式-策略模式
  7. Jacob操作Word文档插入表格并表格中插入图片案例
  8. libreCAD源码阅读笔记2
  9. 【PTA】7-7 大炮打蚊子
  10. PHP取整,四舍五入取整、向上取整、向下取整、小数截取