一、流的概念与作用
流(Stream): 在Java IO中,流是一个核心的概念。流从概念上来说是一个连续的数据传输过程。人们根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。你既可以从流中读取数据,也可以往流中写数据。流的特性与数据源或者数据流向的媒介相关联。
作用:为数据源和目的地建立一个输送通道。
在Java IO中按照数据单位将流分为两类:
1.字节流:以字节为单位进行读写 1字节(byte) = 8位(bit)。
2.字符流:以字符为单位进行读写 1字符 = 2字节)。
字节流和字符流的区别(重点):
1.字节流没有缓冲区,是直接输出的,而字符流是输出到缓冲区的。因此在输出时,字节流不调用colse() 方法时,信息已经输出了,而字符流只有在调用close() 方法关闭缓冲区时,信息才输出。要想字符流在未关闭时输出信息,则需要手动调用flush() 方法。
2.读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。
3.处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。
结论:对于处理纯文本数据,优先考虑使用字符流。除此之外都使用字节流。
二、流的详细划分
I/O(输入输出的定义):输入(InputStream) 和 输出(OutputStream) 经常容易让人混淆,因为,一个程序的输入,往往是一个程序的输出。
在这里插入图片描述
所以我们说的输入与输出都是相对于当前应用程序而言的,如图:
在这里插入图片描述
InputStream和Reader与数据源相关联(即输入流),
OutputStream和writer与目标媒介相关联(即输出流)。
此外,我们还可以按功能不同分为 节点流、处理流:
节点流:以从或向一个特定的地方(节点)读写数据。如FileInputStream。
处理流:是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。如BufferedReader。处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装。
总结,流的划分可以有很多中:
1.按照流的操作单元划分
字节流:将数据解释为原始的二进制数据读写均为字节,数据不需要编码和解码,效率更高,可移植(与主句编码方式无关)。
字符流: 字符流将原始数据解析成一种字符,文本数据存储 依赖文件编码方式,它输入输出需要编码解码。
2.按照流的方向(输出输入都是站在程序所在内存的角度划分的)
输入流:从别的地方(本地文件,网络上的资源等)获取资源 输入到 我们的程序中。
输出流:从我们的程序中 输出到 别的地方(本地文件), 将一个字符串保存到本地文件中,就需要使用输出流。
3.按角色功能不同划分
节点流,以从或向一个特定的地方(节点)读写数据。如FileInputStream。
处理流,是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。如BufferedReader。处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装。
.
三、Java IO的用途和特征
结合上文,我们可以按照流的操作单元和流方向大体上可将流分为四个基本的流类,所有的流都继承这四个:
字节流 字符流
输入流 InputStream Reader
输出流 OutputStream Writer
java.io包除了这四个基本的抽象流类,除此外java.io包类还提供了大量的子类,每个子类都有其特定的功能与用处,大致分为以下用处:
File Access ( 文件访问 )
Network Access ( 网络访问 )
Internal Memory Buffer Access ( 内存缓存访问 )
Inter-Thread Communication (Pipes) ( 线程内部通信(管道) )
Buffering ( 缓冲 )
Filtering ( 过滤 )
Parsing ( 解析 )
Reading and Writing Text (Readers / Writers) ( 读写文本 )
Reading and Writing Primitive Data (long, int etc.) ( 读写基本类型数据 例如long, int )
Reading and Writing Objects ( 读写对象 )
java.io之所以提供了那么多子类,是因为java基于装饰模式的设计思想来设计io体系的,它为每个子类提供了很极小颗粒度功能的实现,这样当你需要使用流的某一特定功能时,能动态的装配这些Stream类,获取自己想要的流类。
Byte Based Input Byte Based Output Character Based Input Character Based Output
Basic(基本) InputStream OutputStream Reader
InputStreamReader Writer
OutputStreamWriter
Arrays(数组) ByteArrayInputStream ByteArrayOutputStream CharArrayReader CharArrayWriter
Files(文件) FileInputStream
RandomAccessFile FileOutputStream
RandomAccessFile FileReader FileWriter
Pipes(管道) PipedInputStream PipedOutputStream PipedReader PipedWriter
Buffering(缓冲器) BufferedInputStream BufferedOutputStream BufferedReader BufferedWriter
Filtering(过滤器) FilterInputStream FilterOutputStream FilterReader FilterWriter
Parsing(解析) PushbackInputStream StreamTokenizer PushbackReader
LineNumberReader
Strings(字符串) StringReader StringWriter
Data(日期) DataInputStream DataOutputStream
Data - Formatted(格式化日期) PrintStream PrintWriter
Objects(对象) ObjectInputStream ObjectOutputStream
Utilities(工具) SequenceInputStream
四、流的使用详解
在整个Java.io包中最重要的就是5个类和一个接口。5个类指的是File、OutputStream、InputStream、Writer、Reader;一个接口指的是Serializable.掌握了这些IO的核心操作那么对于Java中的IO体系也就有了一个初步的认识了。
主要的类如下:
1. File(文件特征与管理):File类是对文件系统中文件以及文件夹进行封装的对象,可以通过对象的思想来操作文件和文件夹。 File类保存文件或目录的各种元数据信息,包括文件名、文件长度、最后修改时间、是否可读、获取当前文件的路径名,判断指定文件是否存在、获得当前目录中的文件列表,创建、删除文件和目录等方法。
2. InputStream(二进制格式操作):抽象类,基于字节的输入操作,是所有输入流的父类。定义了所有输入流都具有的共同特征。
3. OutputStream(二进制格式操作):抽象类。基于字节的输出操作。是所有输出流的父类。定义了所有输出流都具有的共同特征。
4. Reader(文件格式操作):抽象类,基于字符的输入操作。
5. Writer(文件格式操作):抽象类,基于字符的输出操作。
6. RandomAccessFile(随机文件操作):一个独立的类,直接继承至Object.它的功能丰富,可以从文件的任意位置进行存取(输入输出)操作。
1.字节输入流
在这里插入图片描述
1.ByteArrayInputStream:字节数组输入流,该类的功能就是从字节数组(byte[])中进行以字节为单位的读取,也就是将资源文件都以字节的形式存入到该类中的字节数组中去,我们拿也是从这个字节数组中拿
2.PipedInputStream:管道字节输入流,它和PipedOutputStream一起使用,能实现多线程间的管道通信
3.FilterInputStream :装饰者模式中处于装饰者,具体的装饰者都要继承它,所以在该类的子类下都是用来装饰别的流的,也就是处理类。具体装饰者模式在下面会讲解到,到时就明白了
4.BufferedInputStream:缓冲流,对处理流进行装饰,增强,内部会有一个缓存区,用来存放字节,每次都是将缓存区存满然后发送,而不是一个字节或两个字节这样发送。效率更高
5. DataInputStream:数据输入流,它是用来装饰其它输入流,它“允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型”
6.FileInputSream:文件输入流。它通常用于对文件进行读取操作
7.File:对指定目录的文件进行操作,具体可以查看讲解File的博文。注意,该类虽然是在IO包下,但是并不继承自四大基础类。
8.ObjectInputStream:对象输入流,用来提供对“基本数据或对象”的持久存储。通俗点讲,也就是能直接传输对象(反序列化中使用),
2.输出字节流OutputStream
在这里插入图片描述
1.OutputStream 是所有的输出字节流的父类,它是一个抽象类。
2.ByteArrayOutputStream、FileOutputStream 是两种基本的介质流,它们分别向Byte 数组、和本地文件中写入数据。PipedOutputStream 是向与其它线程共用的管道中写入数据,
3.ObjectOutputStream 和所有FilterOutputStream 的子类都是装饰流(序列化中使用)。
3.字符输入流Reader
在这里插入图片描述
1.Reader 是所有的输入字符流的父类,它是一个抽象类。
2.CharReader、StringReader 是两种基本的介质流,它们分别将Char 数组、String中读取数据。PipedReader 是从与其它线程共用的管道中读取数据。
3.BufferedReader 很明显就是一个装饰器,它和其子类负责装饰其它Reader 对象。
4.FilterReader 是所有自定义具体装饰流的父类,其子类PushbackReader 对Reader 对象进行装饰,会增加一个行号。
5.InputStreamReader 是一个连接字节流和字符流的桥梁,它将字节流转变为字符流。FileReader 可以说是一个达到此功能、常用的工具类,在其源代码中明显使用了将FileInputStream 转变为Reader 的方法。我们可以从这个类中得到一定的技巧。Reader 中各个类的用途和使用方法基本和InputStream 中的类使用一致。后面会有Reader 与InputStream 的对应关系。