java之I/O系列01——IO概述
目录
一、前言
在我们写的程序中,在变量、数组和对象中存储的数据是暂时存在的,程序结束后它们就会丢失。想要永久地存储程序创建的数据,就需要将其保存在磁盘文件中,这样就可以在其他程序中使用它们。Java的I/O技术可以将数据保存到文本文件、二进制文件甚至是ZIP压缩文件中,以达到永久性保存数据的要求。
在了解java是如何处理文件之前,我们要知道:文件系统和java进程是平行的,是两套系统。文件系统是由OS(操作系统)管理的。文件系统是由文件夹和文件递归组合而成。文件又包括文件中的内容和文件的基本属性(名称、大小、扩展名、修改时间等)。java中的File类(java.io.File)是专门对文件进行操作的类,只能对文件本身进行操作,不能对文件内容进行操作。File类与OS无关,但是会受OS权限的限制。
所以,我们知道,java和文件系统是两套平行的系统,那么,由于文件可能很大,java可能不能一下子将文件全部加载进内存,如果全部加载进内存,可能耗费的内存十分庞大,因此,java读写文件,只能以(数据)流的形式分批读取。
二、IO流概述
2.1 流的概念和作用
流是一组有序的,有起点和终点的字节集合,是对数据传输的总称和抽象。即数据在两设备之间的传输称为流,
流的本质是数据传输,根据数据传输的特性将流抽象为各种类,方便进行更直观的数据操作。
2.2 流的分类
(1)根据处理数据类型的不同分为 字节流和字符流。
字节流:每次读取(写出)一个字节,当传输的资源文件有中文时,就会出现乱码;
字符流:每次读取(写出)两个字节,有中文时,使用该流就可以正确传输显示中文。
(2)根据数据流向的不同分为 输入流和输出流。
输入流:从别的地方(本地文件,网络上的资源等)获取资源输入到我们的程序中;
输出流:从我们的程序中输出到别的地方(本地文件)。
(3)按功能不同分为 节点流、处理流。
节点流:以从或向一个特定的地方(节点)读写数据。如FileInputStream
处理流:是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。如BufferedReader。处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装。
三、IO框架
有了上面的基本概念之后,我们看看java io的框架。
Java语言定义了许多类专门负责各种方式的输入/输出,这些类都被放在java.io包中。其中,所有输入流类都是抽象类InputStream(字节输入流)或抽象类Reader(字符输入流)的子类;而所有输出流都是抽象类OutputStream(字节输出流)或抽象类Writer(字符输出流)的子类。
3.1 输入流
3.1.1 InputStream类
InputStream类是字节输入流的抽象类,是所有字节输入流的父类。该类中所有方法遇到错误时都会引发IOException异常。
InputStream类的具体层次结构如图所示。
从中,我们可以看出:
(1)InputStream是所有的输入字节流的父类,它是一个抽象类。
(2) ByteArrayInputStream、StringBufferInputStream、FileInputStream是三种基本的介质流,它们分别从Byte数组、StringBuffer、和本地文件中读取数据。
(3)PipedInputStream是管道输入流,它和PipedOutputStream一起使用,能实现多线程间的管道通信。
(4)ObjectInputStream 是对象输入流。它和ObjectOutputStream一起,用来提供对“基本数据或对象”的持久存储。
(5)FilterInputStream 是过滤输入流。它是DataInputStream和BufferedInputStream等的父类。BufferedInputStream 是缓冲输入流。它的作用是为另一个输入流添加缓冲功能。DataInputStream 是数据输入流。它是用来装饰其它输入流,它“允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型”。
(6)FileInputStream 是文件输入流。它通常用于对文件进行读取操作。
3.1.2 Reader类
Java中的字符是Unicode编码,是双字节的。InputStream是用来处理字节的,并不适合处理字符文本。Java为字符文本的输入专门提供了一套单独的类Reader,但Reader类并不是InputStream类的替换者,只是在处理字符串时简化了编程。Reader类是字符输入流的抽象类,所有字符输入流的实现都是它的子类。
Reader类的具体层次结构如图所示。
(1) Reader 是以字符为单位的输入流的超类。它提供了read()接口来取字符数据。
(2) CharArrayReader 是字符数组输入流。它用于读取字符数组,它继承于Reader。操作的数据是以字符为单位!
(3) PipedReader 是字符类型的管道输入流。它和PipedWriter一起是可以通过管道进行线程间的通讯。在使用管道通信时,必须将PipedWriter和PipedReader配套使用。
(4) FilterReader 是字符类型的过滤输入流。
(5) BufferedReader 是字符缓冲输入流。它的作用是为另一个输入流添加缓冲功能。
(6) InputStreamReader 是字节转字符的输入流。它是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。
(7) FileReader 是字符类型的文件输入流。它通常用于对文件进行读取操作。
3.2 输出流
3.2.1 OutputStream类
OutputStream类是字节输出流的抽象类,此抽象类是表示输出字节流的所有类的超类。OutputStream类中的所有方法均返回void,在遇到错误时会引发IOException异常。OutputStream类的具体层次如图所示。
(1) OutputStream 是以字节为单位的输出流的超类。OutputStream提供了write()接口从输出流中读取字节数据。
(2) ByteArrayOutputStream 是字节数组输出流。写入ByteArrayOutputStream的数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。可使用 toByteArray() 和 toString() 获取数据。
(3) PipedOutputStream 是管道输出流,它和PipedInputStream一起使用,能实现多线程间的管道通信。
(4) FilterOutputStream 是过滤输出流。它是DataOutputStream,BufferedOutputStream和PrintStream的超类。
(5) DataOutputStream 是数据输出流。它是用来装饰其它输出流,它“允许应用程序以与机器无关方式向底层写入基本 Java 数据类型”。
(6) BufferedOutputStream 是缓冲输出流。它的作用是为另一个输出流添加缓冲功能。
(7) PrintStream 是打印输出流。它是用来装饰其它输出流,能为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式。
(8) FileOutputStream 是文件输出流。它通常用于向文件进行写入操作。
(9) ObjectOutputStream 是对象输出流。它和ObjectInputStream一起,用来提供对“基本数据或对象”的持久存储。
3.2.2 Writer类
Writer类是字符输出流的抽象类,所有字符输出类的实现都是它的子类。Writer类的层次结构如图所示。
(1) Writer 是以字符为单位的输出流的超类。它提供了write()接口往其中写入数据。
(2) CharArrayWriter 是字符数组输出流。它用于读取字符数组,它继承于Writer。操作的数据是以字符为单位!
(3) PipedWriter 是字符类型的管道输出流。它和PipedReader一起是可以通过管道进行线程间的通讯。在使用管道通信时,必须将PipedWriter和PipedWriter配套使用。
(4) FilterWriter 是字符类型的过滤输出流。
(5) BufferedWriter 是字符缓冲输出流。它的作用是为另一个输出流添加缓冲功能。
(6) OutputStreamWriter 是字节转字符的输出流。它是字节流通向字符流的桥梁:它使用指定的 charset 将字节转换为字符并写入。
(7) FileWriter 是字符类型的文件输出流。它通常用于对文件进行读取操作。
(8) PrintWriter 是字符类型的打印输出流。它是用来装饰其它输出流,能为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式。
3.3 以字节为单位的输入流和输出流的关联框架图
3.4 以字符为单位的输入流和输出流关联的框架图
3.4 字节和字符的输入流对应关系
3.5 字节和字符的输出流对应关系
本文地址:https://blog.csdn.net/ysz171360154/article/details/107284966