javaIO -- 流的体系设计思路、基础分类
一、流
1. 流的含义
在程序设计中,流是对于数据流动传输的一种抽象描述任何有能力产出数据的数据源,或者有能力接受数据的接收端对象都是一个流。
2. 流的源和目的
数据可能从本地文件读取,或者写入, 也可能发送到网络上,这就是源和目的。
1.文件 最基本的一个数据源就是我们前文提到过的文件,文件不仅java中有,其他语言中也拥有文件的概念 2.字节数组 数据最基本的单位是字节。数组是在程序设计中,为了处理方便, 把具有相同类型的若干变量按有序的形式组织起来的一种形式。这些按序排列的同类数据元素的集合称为数组,所以字节数组,自然是为了更方便操作字节的一种数据组织形式 3. 字符数组/String对象 既然数组可以简化更方便的进行操作,而且也有字节数组,是不是还应该有字符数组呢? 而且,java中的String对象 ,它的内部实现也是char数组,java中使用char表示字符,这不就是字符数组么 4. 管道 "管道"的概念也是类似字面含义,一端输入,就可以从一端流出,就好像一个水管一样,主要用来多线程之间直接进行数据交互,所以说数据来源也可能是一个管道 5.网络等 其他数据源比如网络等,java的强项就是WEB,从网络接收数据是再自然不过的事情 6.流 另外流本身也可以作为一种源,所以一个流的源可以来自另外的一个流
3.流的方向
同水管里面的流水一样,也是只有两个方向,流进或者流出,也就是我们常说的输入 和 输出
4. 流的数据形式:
数据的具体形式就是流传送的内容,可能是字节,也能是字符,或者是其他数据,这就是数据的形式。
计算机存储数据是二进制的 0 1 序列。计算机中存储容量的最小的单位是位(bit)最基本的单位是字节(byte) 字节是通过网络传输信息(或在硬盘或内存中存储信息)的单位,也就是说任何其他形式的数据,都可以并且最终也都是用字节来表示,所以数据最基本的形式就是字节 1 byte = 8 bit
我们的世界充满了各种符号,字符是表示数据和信息的字母、数字或其他符号 在电子计算机中,每一个字符与一个二进制编码相对应,这是一个编码的过程 所以说,数据的基本形式有 字节 和 字符两种形式
5.流的中间形式:
对于任何一个流对它的功能进行一些必要的扩充,就好像接上了转接头的流可以接到其他规格的水管一样。在一个流的基础上 包装,装饰上其他的一些功能,流就会变得更加强大。
放学回家的例子,我们很清楚的知道,火车和汽车是我们 人的中间形式过程,经过转换(买票上车), 地上的人看不到我们了,看到的只是火车
对于流来说,中间形式是什么样子的呢? 比如我们想要把一个Int类型直接写入到文件中,怎么办呢?我们是不是需要把这个类型的数据处理下 转换下呢 或者说包装下 就如同你坐上了车(车把你装了进去,形式就是车),总之就是要处理下。
比如想要缓冲,按照行,按照字等等这就是一种中间形式,后面我们会详细介绍涉及到的中间形式
不过很显然,中间形式并没有向从某种数据源读取数据那么刚需。但是他会给你提供更多的功能,让你的流功能更加多变,扩展。 如果有了中间形式,你可能就能够直接把一个int写入到文件上,这不是很方便么 。
二、javaIO的体系结构
java IO
(一)、流的四大家族
如果先不考虑数据的来源,根据流的方向(输入 和 输出)以及流的数据形式(字符 和 字节) 我们有四种形式
四种形式 | 输入字节 | 输出字节 | 输入字符 | 输出字符 |
Java中名称 | InputStream | OutPutStream | Reader | Writer |
节点流和过滤流
我们上面讲述流的含义概念时,反复提到了流的基本功能以及中间形式,基本功能就是针对于不同数据源的操作,属于刚需范围,而中间形式则是刚需的强有力的增强。流的数据源/目的 流的方向 流的数据类型的组合,构成了基本功能的完整集合。
而对于增强型的流的形式,则是Java IO出彩的地方,属于增强型的功能:java中针对于基本数据源进行操作的流叫做 节点流;对于那些起到增强装饰功能的流,叫做过滤流
(二)、流的体系结构详解
2.1 InputStream节点流
数据源与InputStream的结合 (java.io)
字节数组:ByteArrayInputStream
文件:FileInputStream
管道:PipedInputStream
String:StringBufferInputStream
对象:ObjectInputStream
InputStream过滤流
介绍过了InputStream的节点流,我们看下,我们还希望InputStream能够哪些扩展的功能,也就是上面提到过的 流的中间形式。 我们之前就提到过,希望能够有直接操作数据类型的流,通过这个流可以直接操作基本数据类型的读写,而不需要自己去处理字节或者字节数组等。 也就是说我们希望能够对基本数据类型进行支持 IO是操作系统的瓶颈,如果过于频繁的直接对磁盘IO进行读写,势必会增加CPU的空闲,性能降低,我们希望能够有缓冲的功能 IDE开发工具的编辑器都有行号的标志,行号可以给我们提供很多的便捷性,所以希望能够跟踪展示行号 于是就有支持基本数据类型/缓存/行号/回退 这几种扩展功能的想法
功能点和InputStream组合下可以得到如下四种扩展功能 :
通过装饰者模式来实现过滤流
为什么使用装饰者?
显然我们可以直接通过实现InputStream来实现这几个子类,用于表示这几个功能 但是就又出现了一个问题,如果既想要 支持基本数据类型,又想具有缓冲的功能怎么办? 如果还用继承的想法会出现什么问题? 那就又回到了组合的问题上来了,4种功能就会出现4*3*2*1=24 中组合,类的个数直接爆炸了..... 我们想到设计模式---> 装饰器模式 就可以完美的解决这个问题,装饰器模式是继承的一种良好替代方式,能过有效的避免类的个数的爆炸问题,并且还能够动态的增加或者减少功能
SocketInputStream (java.net) CheckedInputStream (java.util.zip) DeflaterInputStream (java.util.zip) GZIPInputStream (java.util.zip) InflaterInputStream (java.util.zip) ZipInputStream (java.util.zip) JarInputStream (java.util.jar)
2.2.1 OutStream节点流
数据源与OutputStream的结合 (java.io)
字节数组:ByteArrayOutputStream
文件:FileOutputStream
管道:PipedOutStream
对象:ObjectOutputStream
2.2.2 OutputStream过滤流
类似InputStream,OutputStream也需要有支撑基本数据类型的功能,以及缓冲的功能。另外,既然是输出,还希望能够输出各种类型的数据,这样子将会更加方便
基本数据类型支持/缓冲/便捷输出
1. Data表示基本数据类型:DataOutputStream (java.io)
非IO包中的,但是却跟IO相关的一些功能点,跟OutputStream相关的类:
SocketOutputStream (java.net
CheckedOutputStream (java.util.zip
DeflaterOutputStream (java.u
GZIPOutputStream (java.util.zip)
InflaterOutputStream (java.util.zip)
JarOutputStream (java.util.jar) ZipOutputStream (java.util.zip)
2.3.1 Reader节点流
数据源与Reader的结合
字符数组: CharArrayReader (java.io)
String: StringReader (java.io)
文件: FileReader (java.io)
管道: PipedReader (java.io)
对于类的转换,设计模式中使用了适配器模式
通过构造方法接收InputStream,然后通过内部的StreamDecoder处理
StreamDecoder 和 StreamEncoder 是作为字符输入和输出转换的关键类
属于适配器模式中的对象适配器模式 Reader 是Target(目标) InputStream 是 被适配者 Adaptee InputStreamReader 是适配者 Adapter
2.3.2 Reader过滤流
2.4.1 Writer节点流
数据源与writer的结合 (java.io)
字符数组:CharArrayWriter
String:StringWriter
文件:FileWriter
管道:PipedWriter
转换流:OutputStreamWriter
2.4.2 Writer过滤流
1. Buffer表示缓冲 BufferedWriter
2. Print便捷输出:PrintWriter
FilterWriter:类似其他的Filter类,作为装饰器模式的Decoder角色,以便具体的装饰器角色可以使用。
IO类层次结构总结
IO的逻辑功能设计点 由 数据源,流的方向,流的数据形式三部分组合而成,这个组合构成了IO的基本功能
另外还有扩展功能,扩展功能以基础功能作为依托,底层依赖基本功能
每种形式的基本功能和扩展功能构成了该形式的功能的集合
数据源形式比较多,但是对于流的数据形式以及流的方向是固定的
所以所有的类的基础,都是基于 流的数据形式以及流的方向的组合
也就是:字节输入 字节输出 字符输入 字符输出
这四个形式是固定的
分别使用 InputStream OutputStream Reader Writer来表示这四大家族
字节
基本功能对于字节涉及下面几个关键词:ByteArray File Piped Object
扩展功能对于字符涉及涉及下面几个关键词:Buffered Print