java中的io流知识总结_java数据流

java中的io流知识总结_java数据流无意中发现了一个巨牛的人工智能教程,忍不住分享一下给大家。教程不仅是零基础,通俗易懂,而且非常风趣幽默,像看小说一样!觉得太牛了,所以分享给大家。点这里可以跳转到教程。内容概要JavaIO流的设计不得不让人拍案叫绝,佩服设计者鬼斧天工的手法。如果你是Java初学者,我敢保证第一次接触Java的IO类,一定会”狂晕!”,倒不是因为它有多么难学而是太多,而且及其让人有种“不识庐山…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

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

内容概要

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 方法。调用流程图如下:

java中的io流知识总结_java数据流

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 字节的文件。调用关系如下:

java中的io流知识总结_java数据流

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

(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流知识总结_java数据流

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/179974.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 推荐几款好用的手机编程APP!

    推荐几款好用的手机编程APP!各位,很多人现在喜欢用手机写代码,今天小编就带大家盘点几款手机端编程软件。1C4droid【适用编程语言】C/C++【适用平台】Android2.2+【软件介绍】付费软件(国内免费,c4droid是款Android设备上的C/C++程序IDE(集成开发环境),默认以tcc(tinyccompiler)为编译器,可以选择安装gcc插件(20mb,只有root用户可以使用)。最新版为4.03(2013年7月7日更新)。贴吧已发布5.98版本,英文版及汉化版本,默认使用g++编译器,sd

  • 什么叫pure function(纯函数)[通俗易懂]

    什么叫pure function(纯函数)[通俗易懂]在Knockout中,用到了pureComputer(),其原理来自于纯函数(purefunction)。那么,什么叫纯函数呢?纯函数(来自:http://en.wikipedia.org/wiki/Pure_function)     在计算机编程中,假如满足下面这两个句子的约束,一个函数可能被描述为一个纯函数:给出同样的参数值,该函数总是求出同样的结果。该函数结

  • js垃圾处理机制_java中垃圾回收有什么目的

    js垃圾处理机制_java中垃圾回收有什么目的文章目录前置知识堆栈栈堆执行上下文与作用域链执行上下文作用域链一、JavaScript中怎么被定义为垃圾使用局部变量使用对象概括二、两种回收策略标记清理引用计数概括三、什么时候执行垃圾回收关于ChromeV8引擎的GC分代回收指针与活跃对象的区分回收的执行周期四、内存问题五、Es6WeakMap参考文章前置知识堆栈栈什么是栈栈其实是一种数据结构,有着先进后出,后进先出的特性,用生活中的事物来理解最形象的就是汉诺塔了。我们在栈中存储的数据就像汉诺塔的盘子一样,最先放进去在最下面,最后放入的盘.

  • Pycharm 运行py文件[通俗易懂]

    Pycharm 运行py文件[通俗易懂]1 在桌面上建立一个文件夹  2.打开pycharm,如果已经有文件了,就点击File->closeproject,回到主界面3 选择Createanewproject 4.    将该文件夹的所在路径设为工程的路径,选择一下解释器,就点击Create,如果提示该文件夹不空的话,点击yes即可,可以提前把数据放入该aaaa文件夹5.   现在进入该页面,然后新建一个…

  • 国内的微软更新服务器地址,windows update 服务器

    国内的微软更新服务器地址,windows update 服务器SystemCenter2012R2CM系列之部署WindowsServer…1.Windows更新服务器(WindowsServerUpdateService(WSUS))介绍1)技术概述:WindowsServerUpdateServices(WSUS)启用信息技术管理员部署最新的Microsoft产品更新。在WindowsServer2012中,W…

  • microsoft visio 2010激活成功教程版_visio2010激活成功教程版百度云

    microsoft visio 2010激活成功教程版_visio2010激活成功教程版百度云特别说明:软件仅供技术交流,请勿用于商业及非法用途,如产生法律纠纷与本人无关Microsoftvisio2013professional激活成功教程软件下载地址:链接:https://pan.baidu.com/s/1ycZHBzzF2KtGOwAs1LbHMQ密码:npkl激活成功教程步骤:文件—>账号—>更改产品密钥—>输入如下序列号即可。序列号:…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号