文章目录

  • IO 类图
  • 看个例子
  • 装饰者模式
    • OutputStream家族类:
  • 清晰起来了
    • InputStream家族类:
    • Writer家族类:
    • Reader家族类:
    • 再看个例子
  • 最后的话

IO 类图

小帅最近在学Java的IO类库,这么多类看得小帅人头昏眼花,常常是学了这个类,忘了那个类,再过一阵子就全忘了。。。

每次用到的时候,小帅都要重新读文档,看代码,如此循环,身心疲惫。

小帅没办法只好向好朋友小会求助:IO类库太复杂了,我毫无头绪,能不能帮我梳理一下?

小会想了一下,说道:总体来说IO类库分为两大类:字节流字符流,字节流是按字节读取数据,字符流是按字符读取数据。

小帅不解:所有的数据在计算机中都是二进制表示的,都用字节来读取不就行了吗?为什么还要加个字符流,我用字节读出来,再转成字符不行吗?

小会说:Java中的字符都是用Unicode表示的,即对应一个数字,也就是码点。

如果我们用二进制的字节流读出来是无法看懂的,我们需要用对应的编码格式(比如:UTF-8,UFT-16等)转换成我们可读的字符。

字符流就是专门用来读写人们可读的字符的,这样会方便很多,一步到位,不用再手工转换成字符了。

我把IO类都放在一张图里,这样看上去就清爽了:

小帅:还是好多类啊。。。
小会:别急,我们往下看。

看个例子

我们看一下用字节流,把int数据1到9,写进txt文件的例子:

FileOutputStream outputStream = new FileOutputStream("text.txt");
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);for(int i = 0; i < 10; i++) {dataOutputStream.writeInt(i);}dataOutputStream.close();

text.txt文件内容:

里面保存的都是二进制数据,但是我们是用int的数据类型写进去的(dataOutputStream.writeInt(i);),而不是以二进制的格式写进去的。

小帅疑惑:为什么要用 DataOutputStream写入int数据呢?我直接用 FileOutputStream 不能写吗?DataOutputStream有什么作用呢?

小会微微一笑:如果不用DataOutputStream也可以,不过要自己拼成int数据类型的格式,一个int类型占四个字节,比如1用二进制表示就是 0000 0000 0000 0000 0000 0000 0000 0001,用十六进制表示就是 00 00 00 01。

我们试一下用 FileOutputStream 写入int数字 0,1,2:

 FileOutputStream outputStream = new FileOutputStream("text.txt");// int 0outputStream.write(0);outputStream.write(0);outputStream.write(0);outputStream.write(0);// int 1outputStream.write(0);outputStream.write(0);outputStream.write(0);outputStream.write(1);// int 2outputStream.write(0);outputStream.write(0);outputStream.write(0);outputStream.write(2);outputStream.close();

写入结果:

如果用DataOutputStream 写就是:dataOutputStream.writeInt(0),dataOutputStream.writeInt(1),dataOutputStream.writeInt(2),这样是不简单很多呢?

小帅似乎有点懂了:我知道了,DataOutputStream 是对 FileOutputStream 类功能的增强,让FileOutputStream 类更加强大,起到了装饰的作用。

小会开心道:你说到重点了,IO类看似凌乱,其实有一个精巧的设计模式,贯穿其中,把这么多类有序的组织起来了,这个设计模式是理解IO类的钥匙,你知道是哪一个设计模式吗?

装饰者模式?小帅疑惑道。

装饰者模式

是的,就是装饰者模式,我以前写过一篇介绍装饰者模式的文章,可以点开看看:装饰模式–小美的生日蛋糕。

装饰者模式的类图:

OutputStream家族类:

这里的FilterOutputStream类就是装饰模式中的抽象装饰类,它的子类BufferedOutputStream,DataOutputStream,PrintStream就是具体的装饰类,起到了功能增强的作用,它们本身并没有实现写数据的功能。

看下FilterOutputStream的代码:

写数据的功能是靠被修饰的类实现的,这里的OutputStream out 是要从外面传进来的:


DataOutputStream的writeInt方法实现了功能的增强,可以直接写int类型的数据:

BufferedOutputStream类实现了缓存的功能增强:

也就是说装饰类是给主类锦上添花,主类是锦,装饰类是花,花不能代替锦,主要的功能还得靠“锦”实现的。

清晰起来了

同理我们来看看其他流:

InputStream家族类:

Writer家族类:


小帅一眼看出了问题:奇怪,FilterWriter装饰类怎么没有子类呢? 是不是Writer家族没有用装饰模式呢?

小会微微一笑:不是的,其实还是用了装饰模式,只是实现的方式有点不一样,例如OutputStreamWriter类:


其实是对OutputStream类的装饰,换句话说字符流的底层其实是调用了字节流,这也很容易理解,因为计算机只能处理二进制数据,本质上还是通过字节流实现的。

Reader家族类:


FilterReader充当了抽象装饰类,PushbackReader是具体的装饰类。

同样的InputStreamReader类其实也实现了装饰模式:

再看个例子

public static void main(String[] args) throws IOException {try(BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("把酒问月·故人贾淳令予问之.txt")))) {writer.write("青天有月来几时?我今停杯一问之。");writer.newLine();writer.write("人攀明月不可得,月行却与人相随。");writer.newLine();writer.write("皎如飞镜临丹阙,绿烟灭尽清辉发。");writer.newLine();writer.write("但见宵从海上来,宁知晓向云间没。");writer.newLine();writer.write("白兔捣药秋复春,嫦娥孤栖与谁邻。");writer.newLine();writer.write("今人不见古时月,今月曾经照古人。");writer.newLine();writer.write("古人今人若流水,共看明月皆如此。");writer.newLine();writer.write("唯愿当歌对酒时,月光长照金樽里。");}try(BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("把酒问月·故人贾淳令予问之.txt")))) {String line;while((line = reader.readLine()) != null) {System.out.println(line);}}
}

输出:

青天有月来几时?我今停杯一问之。
人攀明月不可得,月行却与人相随。
皎如飞镜临丹阙,绿烟灭尽清辉发。
但见宵从海上来,宁知晓向云间没。
白兔捣药秋复春,嫦娥孤栖与谁邻。
今人不见古时月,今月曾经照古人。
古人今人若流水,共看明月皆如此。
唯愿当歌对酒时,月光长照金樽里。

OutputStreamWriter增强了FileOutputStream,让它拥有了直接写字符的能力,BufferedWriter增强了OutputStreamWriter,让它拥有了缓存的能力。

同样的,InputStreamReader增强了FileInputStream,让它拥有了直接读字符的能力,BufferedReader增强InputStreamReader,让它拥有了缓存的能力。

最后的话

Java的IO类库以前我也看得一脸懵逼,总是觉得太繁琐,太难记了。后来学了装饰者模式才知道,要搞懂Java的IO类库,其实重点是要搞懂装饰者模式。

如果不懂装饰者模式,看多少次也不会理解为什么要这么设计。

当一把锁被锁上的时候,你一直盯着锁看是没有用的,因为钥匙肯定不是插在锁上,一定要去别的地方找钥匙啊。

(欢迎你关注我的公众号:编程我也会)

戴上装饰者模式的眼镜,看透Java I/O相关推荐

  1. (十)装饰器模式详解(与IO不解的情缘)

    作者:zuoxiaolong8810(左潇龙),转载请注明出处. LZ到目前已经写了九个设计模式,回过去看看,貌似写的有点凌乱,LZ后面会尽量改进. 那么本章LZ和各位读友讨论一个与JAVA中IO有着 ...

  2. 设计模式学习(三)——装饰器模式

    前言 距离上一次正儿八经地写随笔已经有一段时间了,虽然2月10号有一篇关于泛型的小记,但是其实只是简单地将自己的学习代码贴上来,为了方便后续使用时查阅,并没有多少文字和理解感悟.之所以在今天觉得有必要 ...

  3. java装饰者模式讲解视频教程_java装饰者模式介绍(图文教程)

    java装饰者模式介绍(图文教程).装饰者模式UML类图: 装饰者模式UML类图 java装饰者模式知识要点 装饰者模式动态地将责任附加到对象上.若要扩展功能,装饰者提供了比继承更有弹性的替代方案. ...

  4. 第 17 章 设计模式(3 装饰者模式)

    一.提出需求 咖啡馆订单系统项目(咖啡馆): 1. 咖啡种类/单品咖啡:Espresso(意大利浓咖啡).ShortBlack.LongBlack(美式咖啡).Decaf(无因咖啡): 2. 调料:M ...

  5. java中的装饰者模式[63]

    java中的装饰者模式[63] 文章目录 java中的装饰者模式[63] 一.什么是装饰者模式? 二.装饰者模式要点 三.代码演示 四.小结 一.什么是装饰者模式? **1.意图:**动态的给一个对象 ...

  6. 结构型设计模式(二) 之 装饰者模式可给对象一层层加工

    1 定义 装饰者模式(Decorator Pattern)又叫包装模式属于结构型设计模式之一,它主要用于动态地给一个对象增加一些额外扩展的功能,它是继承关系的一个替代方案,且在特定场景中比使用继承生成 ...

  7. Java/Android 设计模式系列(7)--装饰者模式

    这篇将会介绍装饰者模式(Decorator Pattern),装饰者模式也称为包装模式(Wrapper Pattern),结构型模式之一,其使用一种对客户端透明的方式来动态的扩展对象的功能,同时它也是 ...

  8. java/android 设计模式学习笔记(7)---装饰者模式

    这篇将会介绍装饰者模式(Decorator Pattern),装饰者模式也称为包装模式(Wrapper Pattern),结构型模式之一,其使用一种对客户端透明的方式来动态的扩展对象的功能,同时它也是 ...

  9. 如何利用装饰者模式在不改变原有对象的基础上扩展功能

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 作者:双子孤狼 blog.csdn.net/zwx9001 ...

最新文章

  1. Android系统源码编译最重要的一步
  2. setTimeout和setInterval实现定时器的区别
  3. ftp安装遇到的问题
  4. spring-mvc里的 mvc:resources 及静态资源访问
  5. tb项目管理实践_项目经理与项目管理整理
  6. 嵌入式工作笔记0001---认识SoC
  7. linux glance删除命令,OpenStack Glance v2 API任意文件删除漏洞(CVE-2012-5482)
  8. 【Spring】学习SpringAOP
  9. 买麦网重要域名遭抢注 质疑遭受阿里巴巴干扰
  10. 无线AP与无线路由器都有些什么区别?(一)
  11. 让机器看了几千万篇热门文章总结的17类热门标题方式模板
  12. 卸载mysql front_完全卸载mysql
  13. 工作缺点和不足及措施_工作总结中的不足与改进该怎么写?
  14. web(vue) 简单使用 mixpanel 网页埋点
  15. 给screen的会话改名字
  16. 计算机作业实验报告dw感想,微机实验报告
  17. OpenStack裸金属使用总结
  18. 巴比特 | 元宇宙每日必读:传腾讯成立XR部门,元宇宙板块再次上涨,多家券商发报告关注虚拟人的投资机会...
  19. 《Adobe Fireworks CS5中文版经典教程》——1.4 配置面板和面板组
  20. linux 常用命令全称

热门文章

  1. 网络服务与配置管理——————6、Windows下V*N设置
  2. iNFTnews | 86年前的DAO:嗜酒者互诫协会
  3. Convention插件-content
  4. 如何管?施工项目才能实现履约创效
  5. 电商系统售后履约流程
  6. 电脑文件或文件夹更改图标
  7. 视频教程-FFmpeg音视频编码实战屏幕录像机视频课程-基于QT5和FFMpegSDK-C/C++
  8. 转回原来服务器物品带锁吗,梦幻西游转服后转角色,转服后寄售角色条件
  9. 什么是工作流管理系统
  10. 【每日早报】2019/12/11