java BIO理解
一、介绍
我自己对BIO的印象一直比较模糊,用到的时候经常百度一下就直接使用。直观的感觉就是一堆类以及使用中的各种嵌套,让人觉得摸不着头脑。本文将从设计模式的角度来介绍BIO的设计及使用,希望各位看官能静下心来,一起思考。
二、设计模式
说到IO,大家都会想到IO流,其实这也是IO的本质。在BIO中,不论是字节流还是字符流,最终都是字节流。理论上,jdk只需要提供了字节流的输入输出功能,我们便可以做所有的事情。但是为了使用方便,jdk又在字节流的输入输出功能上,又做了各种各样的封装来提供一些增强功能以满足常用的开发需求,比如增加缓冲区、字符流等。BIO的封装思路主要是采用装饰者模式和适配器模式。
装饰者模式,通俗点说就是在基础类的外层又包了一层包装类,基础类作为包装类的成员变量存在。包装类借助于基础类可以提供增强型的功能。比如BufferedInputStream可以将FileInputStream包装起来,就实现了带有缓冲区的文件输入输出功能,并且会额外提供一些缓冲区的操作方法。如果jdk不提供BufferedInputStream,我们也可以自己写一个类似的包装类。很多的博客在介绍到装饰者模式时都会提一下为什么不用继承。这里我还是跟大家一样的说法,如果全部采用继承方式的话,会造成类爆炸。而装饰者模式可以使BufferedInputStream在成员变量中维护一个接口InputStream,便可以包装所有的子类。
适配器模式,一个很形象的例子就是充电插口,比如插脚是扁的,插孔是圆的,想要将插脚插到插孔里,就需要一个适配器来连接两者。在BIO里,需要适配器的地方是字节流与字符流的转化。我们都知道BIO提供了Reader和Writer来操作字符流,他们的底层其实还是字节流,只不过是通过适配的方式,将字节流转成了字符流。
三、装饰者模式举例
1、FileInputStream
File file = new File("D:\\test.txt");
InputStream fileInputStream = new FileInputStream(file);
byte[] bytes = new byte[1024];
//字节数组的可用长度
int aval = 0;
while((aval = fileInputStream.read(bytes))>0){
System.out.println(new String(bytes,0,aval));
}
FileInputStream作为基础类,只有基础的字节流输入输出功能,每次都从文件中读取。
2、BufferedInputStream(缓冲区增强)
File file = new File("D:\\test.txt");
InputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(file));
byte[] bytes = new byte[1024];
//字节数组的可用长度
int aval = 0;
while((aval = bufferedInputStream.read(bytes))>0){
System.out.println(new String(bytes,0,aval));
}
BufferedInputStream内部有一个字节数组,默认大小是8192字节,当首次读取数据时会通过FileInputStream一次性读入8192字节的数据,之后的读取都会首先从缓冲区中读取。
四、适配器模式
1、InputStreamReader(同OutputStreamReader)
File file = new File("D:\\test.txt");
BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
System.out.println(bufferedReader.readLine());
以上代码并没有体现适配器模式,只是字符流的一个简单使用。适配器模式需要在源码里体现。FileReader继承自InputStreamReader,InputStreamReader成员变量中有StreamDecoder流解码器并且构造函数中需要InputStream,StreamDecoder的成员变量中有InputStream。当Reader调用read方法时,底层上还是用InputStream读字节流,然后经过StreamDecoder解码形成字符流。
原文地址:https://www.cnblogs.com/ssl-bl/p/12932109.html
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- 5.01-requests_auth
- Git分支操作
- 5.02-requests_proxy
- 5.03-requests_ssl
- 5.04-requests_cookies
- 通过 Node.js 小示例学习浏览器缓存策略
- [未解决]报错: execjs._exceptions.ProgramError: TypeError: Cannot read property 'extend' of undefined
- 5.05-requests_cookies2
- 5.06-re
- Python3爬虫 利用百度地图api得到城市经纬度
- [未解决]报错: pytesseract.pytesseract.TesseractNotFoundError: tesseract is not installed or it's not in y
- 6.01-re-split_chinese
- Mac上安装tesseract-OCR
- 6.02-news_re
- 6.03-news_xpath2