IO流学习笔记(基础)

笔记记的是一个博客园的博主的。

目录

Input(输入)读 Read,粘贴分享 临时性

Output(输出)写 Write,复制保存 持久化

File 类

构造方法

获取功能的方法

判断功能的方法

创建/删除功能的方法

做目录的遍历

在这么多的功能方法的支持下,我们可以递归遍历文件夹下的所有文件及其子文件

File 的绝对路径和相对路径

字节/字符流(以基本操作单位为区分的流),依次介绍四大流

第一大流 字节 输出流(OutputStream)

例子:文件 输出流(FileOutputStream)

第二大流 字节 输入流(InputStream)

例子:文件 输入流(FileInputStream)

字符 流(降低兼容,提升效率)

第三大流 字符 输入流(Reader)

第四大流 字符 输出流(Writer)

特殊点:关闭 close 和 刷新 flush

1.缓冲流(高效流)

字节 缓冲流(Buffered [In/Out] putStream)

字符 缓冲流(Buffered [Read/Writ] er)

2.转换流(解码/编码流)

字节转字符流 / 解码流(InputStreamReader)

字符转字节流 / 编码流(OutputStreamWriter)

3.序列化流(对象流)

对象输出流 ObjectOutputStream 写

对象输入流 ObjectInputStream 读

4.打印流(显示输出流)

5.数据流(包裹运输流)Data [In/Out] putStream

6.Properties 属性类

7.提一嘴节点流和包装流(处理流)

节点流和处理流的区别和联系

处理流的功能主要体现在以下两个方面


首先什么是 IO 流,流呢?是一种抽象概念(比喻数据的无结构化传递像“流”)。

而 IO 即 input(输入) 和 output(输出),代表了输入和输出操作。

 在IO流里,输入/输出分为4步:格式化/解析,缓冲,编码转换和传递。                

 想想看,当我们要把货车上的货物搬运到仓库里需要几步?

        1.确定搬运方式,比如是液体就用瓶子,是固体就用绳子。(格式化/解析)

        2.搬运工人在搬运时的过程就承接到了缓冲的作用。(缓冲)

        3.比如这个货物原来是果子,但当地人喜欢喝果汁,所以就把果子转化成果汁,感觉果汁更适应运输。(编码转换)

        4.一切准备好了,就开始传递了。(传递)bit 单位。

前言,我们每次参与 IO 流操作的时候,必须明确四个目的:

  1. 自己要输入流(读书)还是输出流(写书)
  2. 明确流的两端的数据各自是字节(byte)还是文本/字符(character)
  3. 确定流的两端的设备,比如键盘(System.in)和屏幕(System.out)
  4. 根据实际情况是否需要额外功能或加工?比如需要使用转换流等等

Input(输入)读 Read,粘贴分享 临时性

意思就是我们在读取,比如读书、粘贴操作(当我们已复制的前提下,我们想看看复制的内容是什么时,我们就会把它 Ctrl + V 粘贴出来,目的在于分享)

输入流 分类
分类(字节 byte / 字符 character): 字节 输入流 字符 输入流
基类(超类): InputStream Reader
访问文件: FileInputStream FileReader
访问数组: ByteArrayInputStream CharArrayReader
访问管道: PipedInputStream PipedReader
访问字符串: - StringReader
缓冲流: BufferedInputStream BufferedReader
转换流: - InputStreamReader
对象流: ObjectInputStream -
抽象基类(也叫抽象超类): FilterInputStream FilterReader
打印流: -
推回输入流: PushbackInputStream PushbackReader
特殊流: DataInputStream -
注解:倾斜 + 下划线 = 抽象类,无法创建实例;而红色的代表节点流,必须直接和指定的物理节点关联。- 代表缺省(此注解下个表格同样适用)

Output(输出)写 Write,复制保存 持久化

意思就是我们在记录,比如写书、复制操作(当我们想记住什么时,我们就会把它 Ctrl + C 复制起来,目的在于保存)

输出流 分类
分类(字节 byte / 字符 character): 字节 输出流 字符 输出流
基类(超类): OutputStream Writer
访问文件: FileOutputStream FileWriter
访问数组: ByteArrayOutputStream CharArrayWriter
访问管道: PipedOutputStream PipedWriter
访问字符串: - StringWriter
缓冲流: BufferedOutputStream BufferedWriter
转换流: - OutpurStreamWriter
对象流: ObjectOutputStream -
抽象基类(也叫抽象超类): FilterOutputStream FilterWriter
打印流: PrintStream PrintWriter
推回输入流: - -
特殊流: DataOutputStream -
注:以后会补充全比照的表格

我们再来细说里面的类

File 类

java.io.File       

  1.         专门操作文件这个“壳子”的类,即只操作文件本身,而不操作文件里的内容/数据。
  2.         可以是文件和目录路径名的抽象表示,主要是文件和目录的创建、查找和删除等等操作      

解析上面的两句话:一是File(文件)跟流无关,因为 File 类不能对文件进行 IO 操作(读写操作或输入输出操作);二是 D:\\文件夹 和 D:\\文件目录\\文件.txt,都是File类的操作对象(即文件夹和文件本身),其实文件夹只是一种“特殊”的文件罢了。

在 Java 中一切都是对象,我们要参与 File 类就先构造一个它的对象。

构造方法

File(File parent, String child)根据 parent 抽象路径名(文件目录)+ child 路径名字符串(文件路径)创建一个新 File 实例

File(String pathname)通过全路径名来创建一个新 File 实例

File(String parent,String child)根据 parent 路径名字符串和 child 路径名字符串来创建一个新 File 实例

File(URI uri)通过给定的file:URI转换为一个抽象路径名来创建一个新的File实例

获取功能的方法

1. public String getAbsolutePath():返回字符串 =  File 的绝对路径名

2. public String getPath():返回字符串 = File 的路径名

3. public String getName():返回字符串 = File 的文件/目录名称

4. public long length():返回 long 数据 = File 的文件长度(单位:字节 byte)

判断功能的方法

1、 public boolean exists() :此File表示的文件或目录是否实际存在。


2、 public boolean isDirectory() :此File表示的是否为目录。


3、public boolean isFile() :此File表示的是否为文件。

创建/删除功能的方法

  1. public boolean createNewFile() :文件不存在,创建一个新的空文件并返回true,文件存在,不创建文件并返回false
  2. public boolean delete() :删除由此File表示的文件或目录。
  3. public boolean mkdir() :创建由此File表示的目录。
  4. public boolean mkdirs() :创建由此File表示的目录,包括任何必需但不存在的父目录。
  5. 其中,mkdirs() mkdir()方法类似,但 mkdir(),只能创建一级目录,mkdirs()可以创建多级目录比如//a//b//c,所以开发中一般用mkdirs();

这些方法中值得注意的是createNewFile方法以及mkdirmkdirs的区别

主要是创建文件和文件目录的区别

做目录的遍历

1. public String[] list():返回字符串 = 代表 File 的所有子文件/目录

2. public File[] listFiles():返回一个 File 数组 = 代表 File 目录下的所有子文件/目录(一级目录)

在这么多的功能方法的支持下,我们可以递归遍历文件夹下的所有文件及其子文件

Java代码总结:

public class RecursionDirectory {
    public static void main(String[] args) {
        File file = new File("D:\\play");
    //  创建一个 File,记录文件路径
        Recursion(file);
    //  调用递归方法
    }
    public static void Recursion(File file) {
    //  递归方法,相当于榨汁机把自己榨出的果汁再放入自己里面再榨一边
        if (!file.isDirectory()) {
        //  判断不是“目录”,就直接退出递归方法
            return;
        }
        File[] files = file.listFiles();
        //  既然已经确定是“目录”了,就使用 listFiles() 方法来遍历一遍其下的子文件/目录    
        for (File f:files) {
        //  使用增强 for 循环来遍历 files 数组         
            if (f.isDirectory()) {
                Recursion(f);
            //  确定是目录就继续调用递归方法      
            } else {
                System.out.println(f.getName());
            //  否则是文件的话,就把它文件名给打印了            
            }          
        }        
    }
}

File 的绝对路径和相对路径

绝对路径:一个完整、从头至尾的路径,以盘符开头,如:“D://Document//A//record.txt”

相对路径:一个简化、去头至尾的路径,不以盘符开头,如:“//A//record.txt”

路径书写格式的主要区别是分隔符的书写,如:

        第一种        "C:\learn\english\a"

        第二种        "C:\\learn\\english\\a"

        第三种        "C:/learn/english/a"

字节/字符流(以基本操作单位为区分的流),依次介绍四大流

前者以字节 byte 为单位(根据bit),后者以字符 character 为单位(根据字符集)

综合起来,按输入、输出、字节、字符四个特点来分类的话,就有四个“祖宗”(基类/超类)

四大流的分类表格
输入流 输出流
字节流 字节输入流        InputStream 字节输出流        OutputStream
字符流 字符输入流        Reader 字符输出流        Writer

它们发展来的“子孙后代”多可以见到其名字的“祖宗”名后缀。

        在细说字节/字符流之前,首先明确的是它们最底层始终是二进制数据,即0101...拼凑而成的一个个的字节。所以字节流的兼容性和操作范围是最广的,那么字符流存在的意义是什么呢?这点我们后面再解释,别着急。

第一大流 字节 输出流(OutputStream)

字节输出流类流下的流的基本共性功能方法:

  1.  public void close() :关闭此输出流并释放与此流相关联的任何系统资源。
  2.  public void flush() :刷新此输出流并强制任何缓冲的输出字节被写出。
  3.  public void write(byte[] b):将 b.length(长度)个字节从指定的字节数组写入此输出流。
  4.  public void write(byte[] b, int off, int len) :从指定的字节数组写入 len字节,从偏移量 off开始输出到此输出流。 也就是说从off个字节数开始读取一直到len个字节结束
  5.  public abstract void write(int b) :将指定的 字节 输出流。(之所以是 int b,而不是byte或其他类型 是因为其对应的是 read(int b);而为何 read 方法使用的参数类型是 int 呢?这是因为 int 代表的范围大且适合,而byte的 0~255 范围不足以揽括 read 方法可能遇到的所有返回值,综合考虑下采用了 int 类型)

       比方:数据源 byte[] = 小明,偏移量 off = 起点,长度 len = 路程

例子:文件 输出流(FileOutputStream)

字节输出流(四大流皆有)有许多“子孙”,我们先从其最简单的“子孙” —— FileOutputStream 开始。

在Java中不管学什么,只要它能创建对象,就从其构造方法开始入手!

1、 public FileOutputStream(File file):根据File对象为参数创建对象。


2、 public FileOutputStream(String name): 根据名称字符串为参数创建对象。

第二大流 字节 输入流(InputStream)

字节输入流类流下的流的基本共性功能方法:

  1.  public void close() :关闭此输入流并释放与此流相关联的任何系统资源。
  2. public abstract int read(): 从输入流读取数据的下一个字节。
  3.  public int read(byte[] b): 该方法返回的int值代表的是读取了多少个字节,读到几个返回几个,读取不到返回-1

例子:文件 输入流(FileInputStream)

老样子,继续看看其构造方法:

1、 FileInputStream(File file): 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的 File对象 file 命名。


2、 FileInputStream(String name): 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name 命名。

扩展:

FileInputStream 读取字节数据:

一 使用 read()  方法,每次读取一个字节大小 byte 的数据,提升为 int 类型,当读取到此文件末尾时,将返回 -1 标志符

public class FIS_Read {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("read.txt");
    //  name = 相对路径名
        int b;
    //  b 记录标志符        
        while ((b = fis.read()) != -1) {
        //  当遇到 -1 标志符时退出循环    
            System.out.println((char) b);
        //  int 类型强制转换成 char 字符显示(利用字符集码值)
        }
        fis.close();
    }
}

(利用循环和 -1 标志符来循环读取数据流)

二 使用 read(byte[] b) 方法,每次读取 b 数组长度个字节大小 byte,并可以返回读取到的有效字节 byte 数量,同样当读取到文件末尾时,就返回标志符 -1

public class FIS_Read {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("read.txt");
    //  name = 相对路径名
        int len;
    //  len 用来记录标志符
        byte[] b = new byte[3];
    //  b 用来缓冲数据        
        while ((len = fis.read(b)) != -1) {
        //  当遇到 -1 标志符时退出循环    
            System.out.println(new String(b));
        //  byte[] 类型强制转型到 String 再显示    
        }
        fis.close();
    }
}

(数据源每次循环读取 b 大小字节,若不能“整除”;则 b 这个缓冲载体将残留一部分上次读取的数据。在循环读取过程中,b 载体是循环替换显示里面的数据的。

但我们可以改进,已知 read(byte[] b) 方法可以返回此次读取到的有效字节的长度,当我们打印数据时可以选择 System.out.println(new String(b, 0, len)); 这是String 类提供的一个功能方法,即以 0 位为“起点”,len 为“路程”来显示 b 数据。)

例子:利用字节流 FileInputStream 来“克隆”图片,创建副本!

public class Transcript {
    public static void main(String[] args) throws IOException {
    //    利用流对象来指定
    FileInputStream fis = new FileInputStream("D:\\Baby.png");//读
    //    指定数据源
    FileOutputStream fos = new FileOutputStream("D:\\Baby_Transcript.png");//写
    //    指定目的地
    
    byte[] b = new byte[1024];
    //    准备缓冲的载体
    int len;
    //    准备记录每次读取数据的长度
    while ((len = fis.read(b)) != -1) {
        fos.write(b, 0, len);
        //    边读边写出数据
        }
    }
    fos.close();
    fis.close();
    //    安全的关闭流资源!
}

举一反三的话,你还可以“克隆”其它的资源,比如文本、视频等等。

讲完 字节 流中的文件 File 输入/输出流之后,其它的“兄弟”字节流们;只要因材施用,相信你也能融会贯通的!

字符 流(降低兼容,提升效率)

由于各国/组织采用的数据编码方式的不同,所以其字符集也就不同,随运而生的是:专门有了对 字符 进行高效操作的流对象 ;但是字符流本质上还是基于字节流来读取的,只是去查取了特定的字符集(码表),这也是为什么字节流直接读取数据会有乱码的问题(如中文)。

        由此可见以字符为操作单位(其大小 >= 字节 byte)的字符流,其效率较高且专门处理文本类型的文件,其它非文本类型的文件(比如图片、视频等等)就只能使用字节流了。

字符流 = 字节流 + 字符集(编码表)                                具有语言文本性质

第三大流 字符 输入流(Reader)

第三个“祖宗”登场了!请先看看字符输入流的基本共性功能方法:

1、public void close() :关闭此流并释放与此流相关联的任何系统资源。


2、 public int read(): 从输入流读取一个字符。


3、 public int read(char[] cbuf): 从输入流中读取一些字符,并将它们存储到字符数组 cbuf

        再从简单 File 相关类入手,FileReader 类是从读取字符文本文件的便利类。其构造时使用系统默认的字符编码(字符集)和默认字节缓冲区。

以下是其构造方法:

1、FileReader(File file): 创建一个新的 FileReader ,给定要读取的File对象


2、 FileReader(String fileName): 创建一个新的 FileReader ,给定要读取的文件的字符串名称

它的 read 方法也类似于字节输入流,区别是操作单位不同罢了,就不再赘述了。

第四大流 字符 输出流(Writer)

字符输出流的基本共性功能方法:

1、void write(int c) 写入单个字符(以码值)


2、void write(char[] cbuf) 写入字符数组。


3、 abstract void write(char[] cbuf, int off, int len) 写入字符数组的某一部分,off 数组的开始索引,len 写的字符个数。


4、 void write(String str) 写入字符串。


5、void write(String str, int off, int len) 写入字符串的某一部分,off 字符串的开始索引,len 写的字符个数。


6、void flush() 刷新该流的缓冲。


7、void close() 关闭此流,但要先刷新它。

        FileWriter 类是写出字符到文本文件的便利类。其构造时使用系统默认的字符编码(字符集)和默认字节缓冲区。

其构造方法:

1、 FileWriter(File file): 创建一个新的 FileWriter,给定要读取的File对象。


2、FileWriter(String fileName): 创建一个新的 FileWriter,给定要读取的文件的名称。

例子:利用 write(int b) 方法来写出一个字符:

public class FWWrite {
    public static void main(String[] args) throws IOException {
    FileWriter fw = new FileWriter("fw.txt");
    //    首先利用文件名称创建一个流对象
    fw.write(65);//写出第一个字符
    fw.write(97);//写出第二个字符
    fw.weite(48);//写出第三个字符
    //A a 0
//关闭资源时,与FileOutputStream不同 如果不关闭,数据只是保存到缓冲区,并未保存到文件。
    fw.close();
    }
}

特殊点:关闭 close 和 刷新 flush

因为字符流内置缓冲区的原因,如果不关闭输出流,就无法写出字符到文件中。但是已关闭的流对象,显然是无法继续写出数据的。倘若我们既要写出数据,又要继续使用流,就需要 flush 方法了。

flush :刷新缓冲区,流对象可以继续使用。

close :先刷新缓冲区,然后再通知系统释放资源。此流对象不可以再被使用了。

这里有个重要的词——刷新,我们需要刷新让内存缓冲区的数据刷到文件中去。就像把手上的东西确确实实的放到了目的地一样,就是它已经离开了我的手到达了目的地。

注解:flush() 这个函数是清空的意思,用于清空缓冲区的数据流,进行流的操作时,数据先被读到内存中,然后再用数据写到文件中,那么当你数据读完时,我们如果这时调用 close() 方法来刷新、关闭读写流,这时就可能造成数据丢失,为什么呢?因为,读入数据完成时不代表写出数据也全部完成了,还有一部分数据可能会留在缓存区中,这个时候不会关闭流的 flush() 方法就显得格外重要了(可以完成续写操作)。但是最终释放系统资源时还得使用 close() 方法。

1.缓冲流(高效流)

缓冲流的基本原理:

1、使用了底层流对象从具体设备上获取数据,并将数据大量存储到缓冲区的数组内。


2、通过缓冲区的 read() 方法直接从缓冲区获取具体的字符数据,这样就提高了效率。


3、如果用 read() 方法读取字符数据,并存储到另一个容器中,直到读取到了换行符时,将另一个容器临时存储的数据转成字符串返回,就形成了readLine()功能,提高了读取效能。(可以一行一行的读取字符数据了)

即创建流对象时,会创建一个内置的默认大小的缓冲区数组,(像多了一只手)通过缓冲区读写,减少系统IO次数,从而提高读写的效率。

缓冲流按字节、字符分成两类流:

字节 缓冲流(Buffered [In/Out] putStream)

构造方法:

  • public BufferedInputStream(InputStream in) :创建一个新的缓冲输入流,注意参数类型为InputStream

  • public BufferedOutputStream(OutputStream out): 创建一个新的缓冲输出流,注意参数类型为OutputStream

功能使用上与之前的流类似,就是效率高!因为有缓冲区

字符 缓冲流(Buffered [Read/Writ] er)

构造方法:(格式类似字节缓冲流)

  • public BufferedReader(Reader in) :创建一个新的缓冲输入流,注意参数类型为Reader

  • public BufferedWriter(Writer out): 创建一个新的缓冲输出流,注意参数类型为Writer

一样!但是字符缓冲流比原始的字节流多了一些特有的方法:

  • BufferedReader:public String readLine(): 读一行数据读取到最后返回null

(这里的标志符不是 -1 了,而是 null)

  • BufferedWriter:public void newLine(): 换行,由系统属性定义符号。

2.转换流(解码/编码流)

一看到解码/编码就知道转换流跟 字符集 有关。

编码:字符(我)                      ==>        字节(\xced2\x0a)

解码:字节(\xced2\x0a)        ==>        字符(我)

字节转字符流 / 解码流(InputStreamReader)

从名字中也能看出一些“马脚”,InputStream ==> Reader

其中它所关联的字符集我们可以指定,也可以接受平台的默认字符集(通常是UTF-8)。

构造方法:

InputStreamReader(InputStream in): 创建一个使用默认字符集的字符流。


InputStreamReader(InputStream in, String charsetName): 创建一个指定字符集的字符流。

字符转字节流 / 编码流(OutputStreamWriter)

构造方法:

OutputStreamWriter(OutputStream in): 创建一个使用默认字符集的字符流。


OutputStreamWriter(OutputStream in, String charsetName): 创建一个指定字符集的字符流。

有时我们可以在缓冲流内包装转换流,这样既达到了效率又兼顾了功能!如:

BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

3.序列化流(对象流)

Java 提供了一种对象序列化的机制。用一个字节序列可以表示一个对象,该字节序列包含该对象的数据对象的类型对象中存储的属性等信息。字节序列写出到文件之后,相当于文件中持久保存了一个对象的信息,像户口本一样。(保存)

反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化对象的数据对象的类型对象中存储的数据信息,都可以用来在内存中再创建对象。(重现)

对象流将对象转换成字节流,实现对象的持久化存储和网络传输。(便利性)

对象输出流 ObjectOutputStream 写

构造方法:

public ObjectOutputStream(OutputStream out) : 创建一个指定OutputStream的ObjectOutputStream。(像是一种包装)

序列化操作的条件:

        1.该类实现了 java.io.Serializable 接口

        2.该类里的所有属性要么是可序列化的,要是瞬态的(transient)

写对象的方法:序列化

public final void writeObject (Object obj) : 将指定的对象写出。

对象输入流 ObjectInputStream 读

构造方法:

public ObjectInputStream(InputStream in) : 创建一个指定InputStream的ObjectInputStream。

读对象的方法:反序列化

public final Object readObject () : 读取一个对象。

有时反序列化操作也会失败,如抛出 InvalidClassException 异常。原因可能是:

        1、该类的序列版本号与从流中读取的类描述符的版本号不匹配(读写不一致)
        2、该类包含未知数据类型
        3、该类没有可访问的无参数构造方法

Serializable 接口给需要序列化的类,提供了一个序列版本号。

serialVersionUID 该版本号的目的在于验证序列化的对象和对应类是否版本匹配。

4.打印流(显示输出流)

我们平常使用的 print 和 println 方法都来自 java.io.PrintStream 类

特点:

A:只操作目的地,不操作数据源


B:可以操作任意类型的数据


C:如果启用了自动刷新,在调用println()方法的时候,能够换行并刷新


D:可以直接操作文件如果某流的构造方法能够同时接收 File 和 String 类型的参数,一般都是可以直接操作文件的!)

5.数据流(包裹运输流)Data [In/Out] putStream

特点: 八种基本类型的数据在输入/输出时,会保持类型不变,因此,这种流特别适合在网络上实现基本类型数据和字符串的传递。

直接看其功能方法:

readByte() writeByte()
readShort() writeShort();
readInt() writeInt();
readLong() writeLong();
readFloat() writeFloat();
readDouble() writeDouble();
readBoolean() writeBoolean();
readChar() writeChar();
readUTF() writeUTF();

注意:

        1.数据流属于包装流,它必须套接在节点流上。

        2.因为数据类型需对应,所以数据流在读取与存储时的顺序要一致。否则,读取数据会失真。

6.Properties 属性类

流的使用需要许多 数据源 和 目的地 的路径或者是一些修改频繁的配置信息,我们一般喜欢统一保存在 Properties 属性集合里,方便调用。

java.util.Properties 继承于 Hashtable ,来表示一个持久的属性集。它使用键值结构存储数据,每个键及其对应值都是一个字符串。该类也被许多Java类使用,比如获取系统属性时,System.getProperties 方法就是返回一个Properties对象。

构造方法:

public Properties() :创建一个空的属性列表。

存储功能的方法:

  • public Object setProperty(String key, String value) : 保存一对属性。

  • public String getProperty(String key) :使用此属性列表中指定的键搜索属性值。

  • public Set stringPropertyNames() :所有键的名称的集合。

与流相关的方法:

public void load(InputStream inStream): 从字节输入流中读取键值对。

参数中使用了字节输入流,通过流对象,可以关联到某文件上,这样就能够加载文本中的数据了。

而文本数据格式是键值对形式的,如:length=170;

它们中间的分隔符换成空格、冒号等等。

7.提一嘴节点流和包装流(处理流)

其实刚刚的四个流(缓冲流、转换流、序列化流、打印流)都是包装流,而文件输入/输出流就属于典型的节点流。

节点流和处理流的区别和联系

  •     节点流是底层流/低级流,直接跟数据源相接。
  •     处理流(包装流)包装节点流,既可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入输出
  •     处理流(也叫包装流)对节点流进行包装,使用了修饰器设计模式,不会直接与数据源相连

处理流的功能主要体现在以下两个方面

  1.     性能的提高:主要以增加缓冲的方式来提高输入输出的效率
  2.     操作的便捷:处理流可能提供了一系列便捷的方法来一次输入输出大批量的数据,使用更加灵活方便

IO流基础的笔记就先点到为止了,Bye!

你可能感兴趣的:(Java,SE,java,开发语言,笔记)