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
基本功能对于字符涉及涉及下面几个关键词 :CharArray String File Piped
扩展功能对于字符涉及涉及下面几个关键词:Buffered Print
javaIO -- 流的体系设计思路、基础分类的更多相关文章
- [三]JavaIO之IO体系类整体设计思路 流的概念以及四大基础分类
从本文开始,将正式进入JavaIO的简介 在继续javaIO系列的文章之前 可以过去看一下 本人博客上的设计模式中的 适配器模式和装饰器模式 这会对接下来的阅读大有帮助 本文是从逻辑上介绍整个的J ...
- Java基础 Java-IO流 深入浅出
建议阅读 重要性由高到低 Java基础-3 吃透Java IO:字节流.字符流.缓冲流 廖雪峰Java IO Java-IO流 JAVA设计模式初探之装饰者模式 为什么我觉得 Java 的 IO 很复 ...
- IM开发基础知识补课(七):主流移动端账号登录方式的原理及设计思路
1.引言 在即时通讯网经常能看到各种高大上的高并发.分布式.高性能架构设计方面的文章,平时大家参加的众多开发者大会,主题也都是各种高大上的话题——什么5G啦.AI人工智能啦.什么阿里双11分分钟多少万 ...
- 基于Redis的限流系统的设计
本文讲述基于Redis的限流系统的设计,主要会谈及限流系统中限流策略这个功能的设计:在实现方面,算法使用的是令牌桶算法来,访问Redis使用lua脚本. 1.概念 In computer netw ...
- 对RESTful Web API的理解与设计思路
距离上一篇关于Web API的文章(如何实现RESTful Web API的身份验证)有好些时间了,在那篇文章中提到的方法是非常简单而有效的,我在实际的项目中就这么用了,代码经过一段时间的磨合,已经很 ...
- HTTP 协议的历史演变和设计思路
HTTP 协议是互联网的基础协议,也是网页开发的必备知识,最新版本 HTTP/2 更是让它成为技术热点. 本文介绍 HTTP 协议的历史演变和设计思路. 一.HTTP/0.9 HTTP 是基于 TCP ...
- enode框架step by step之消息队列的设计思路
enode框架step by step之消息队列的设计思路 enode框架系列step by step文章系列索引: enode框架step by step之开篇 enode框架step by ste ...
- 【4Large-Style】前端框架设计——Button 的设计思路
Button 的设计 Button 作为基本的 Web 元素,看似简单,却需要非常用心的设计,因为 Button 作为按钮,是具有多个不同的状态,每种状态都基本上需要进行一些特殊的优化设计,以让组件更 ...
- [三]java8 函数式编程Stream 概念深入理解 Stream 运行原理 Stream设计思路
Stream的概念定义 官方文档是永远的圣经~ 表格内容来自https://docs.oracle.com/javase/8/docs/api/ Package java.util.s ...
随机推荐
- Python Tinker学习笔记
一直在简单看看python,这次项目需要做个界面,最好是要跨平台的,之前考虑QT,但是树莓派上QT跨平台编译一直装这有问题,后来发现Python不就可以么? 于是决定用python做个界面,但是做界面 ...
- (7)打造简单OS-加载内核
一.简要说明 我们在第五讲[(5)打造简单OS-进入保护模式]中的mbr.S 汇编文件有段这样的代码 mov eax, 0x2 ; 起始扇区lba地址,从间隔第二个扇区开始 mov bx, 0x900 ...
- Spring Cloud Gateway(八):其它路由谓词工厂
本文基于 spring cloud gateway 2.0.1 6.基于Cookie的谓词工厂 CookieRoutePredicateFactory 是 Cookie 类型的路由断言工厂,接收两个参 ...
- (转)hadoop 集群常用端口
转载于:https://www.cnblogs.com/liying123/p/7097806.html hadoop集群的各部分一般都会使用到多个端口,有些是daemon之间进行交互之用,有些是用于 ...
- kafka 讲讲acks参数对消息持久化的影响
目录 (0)写在前面 (1)如何保证宕机时数据不丢失? (2)多副本冗余的高可用机制 (3)多副本之间数据如何同步? (4)ISR到底指的什么东西? (5)acks参数的含义? (6)最后的思考 ...
- window.postMessage 跨窗口,跨iframe javascript 通信
同源通信 执行它们的页面位于具有相同的协议(http/https),端口(80/443),主机(通常为域名) 时,这两个脚本才能相互通信 大多数情况下,网站就是内部的域名,所以是同源通信,可以相互访问 ...
- JMeter中计数器的使用
添加计数器 计数器的引用,用于数据做区分 可以添加一个变量count,每次为了数据的唯一性,只要修改count就可以了,例如
- SQL优化 | Oracle 绑定变量
之前整理过一篇有关绑定变量的文章,不太详细,重新补充一下. Oracle 绑定变量 http://www.cndba.cn/Dave/article/1275 一.绑定变量 bind variable ...
- 【k8s部署kong一】kong k8s 安装 以及可视化管理界面
官方安装:https://getkong.org/install/kubernetes/ 扩展讲解:https://blog.fleeto.us/post/intro-kong/ 提示:本文是在k8s ...
- angular父组件通过@ViewChild 主动获取子组 件的数据和方法
1.调用子组件给子组件定义一个名称 <app-footer #footerChild></app-footer> 2. 引入 ViewChild import { Compon ...

