JAVA-IO流体系

JAVA-IO流体系

在IO中,具体构件角色是节点流,装饰角色是过滤流。
1、继承自InputStream/OutputStream的流都是用于向程序中输入/输出数据,且数据的单位都是字节(byte=8bit),如图,深色的为节点流,浅色的为过滤流。
在这里插入图片描述
2、继承自Reader/Writer的流都是用于向程序中输入/输出数据,且数据的单位都是字符(2byte=16bit),如图,深色的为节点流,浅色的为过滤流。
在这里插入图片描述
从图中可以看出,InputStream就是装饰者模式中的超类(Component),ByteArrayInputStream,FileInputStream相当于被装饰者(ConcreteComponent),这些类都提供了最基本的字节读取功能。而另外一个和这两个类是同一级的类FilterInputStream即是装饰者(Decorator),BufferedInputStream,DataInputStream,PushbackInputStream…这些都是被装饰者装饰后形成的成品。

为什么可以说:装饰模式可以在不创造更多子类的情况下,将对象的功能加以扩展,能理解这一点就能很好的掌握装饰者设计模式的精髓,如果在InputStream这里扩展出FilterInputStream类下面的装饰类,那么针对FileInputStream和ByteArrayInputStream就都要去实现一次BufferedInputStream了,那么可能就会衍生出BufferedFileInputStream和BufferedByteArrayInputStream这样的类,如果按照这样的扩展方式去添加功能,对于添加功能的子类来说简直是一场噩梦,好在装饰着模式很好的解决了这个问题,现在我们只需要在过滤流类这里维护一个超类,不论传入的是什么具体的节点流,那么都只要套一层装饰,就能对功能方法进行加强。

如果想要对文件输入流进行缓存加强可以这样装饰:

File file = new File ("hello.txt"); 
BufferedInputStream inBuffered=new BufferedInputStream (new FileInputStream(file));

如果想要对字节数组输入流进行缓存加强可以这样装饰:

byte[] byts="Hello".getBytes();
BufferedInputStream bf=new BufferedInputStream(new ByteArrayInputStream(byts));

那么节点流上的类就可以平行扩展,而装饰者同样可以按照功能进行另外一个维度的扩展,调用的时候就可以按需进行组合装饰,这样就可以减少了子类还将对象的功能进行扩展,不得不佩服前人在该设计模式上的智慧,理解了这装饰着模式后,就应该对java中IO流的体系进行梳理:

节点流类型

  • 对文件操作的字符流有FileReader/FileWriter,
  • 字节流有FileInputStream/FileOutputStream。

过滤流类型

  • 缓冲流:缓冲流要“套接”在相应的节点流之上,对读写的数据提供了缓冲的功能,提高了读写效率,同时增加了一些新的方法。
    • 字节缓冲流有BufferedInputStream / BufferedOutputStream,字符缓冲流有BufferedReader / BufferedWriter,字符缓冲流分别提供了读取和写入一行的方法ReadLine和NewLine方法。
    • 对于输出的缓冲流,写出的数据,会先写入到内存中,再使用flush方法将内存中的数据刷到硬盘。所以,在使用字符缓冲流的时候,一定要先flush,然后再close,避免数据丢失。
  • 转换流:用于字节数据到字符数据之间的转换。
    • 字符流InputStreamReader / OutputStreamWriter。其中,InputStreamReader需要与InputStream“套接”,OutputStreamWriter需要与OutputStream“套接”。
  • 数据流:提供了读写Java中的基本数据类型的功能。
    • DataInputStream和DataOutputStream分别继承自InputStream和OutputStream,需要“套接”在InputStream和OutputStream类型的节点流之上。
  • 对象流:用于直接将对象写入写出。
    • 流类有ObjectInputStream和ObjectOutputStream,本身这两个方法没什么,但是其要写出的对象有要求,该对象必须实现Serializable接口,来声明其是可以序列化的。否则,不能用对象流读写。(api以及demo在文末)
重点梳理一下:Java中Inputstream/OutputStream与Reader/Writer的区别
  • Reader/Writer和InputStream/OutputStream分别是I/O库提供的两套平行独立的等级机构,
    • InputStream、OutputStream是用来处理8位元的流,也就是用于读写ASCII字符和二进制数据;Reader、Writer是用来处理16位元的流,也就是用于读写Unicode编码的字符。
    • 在JAVA语言中,byte类型是8位的,char类型是16位的,所以在处理中文的时候需要用Reader和Writer。
    • 两种等级机构下,有一道桥梁InputStreamReader、OutputStreamWriter负责进行InputStream到Reader的适配和由OutputStream到Writer的适配。
  • 在Java中,有不同类型的Reader/InputStream输入流对应于不同的数据源:
    • FileReader/FileInputStream 用于从文件输入;
    • CharArrayReader/ByteArrayInputStream 用于从程序中的字符数组输入;
    • StringReader/StringBufferInputStream 用于从程序中的字符串输入;
    • PipedReader/PipeInputStream 用于读取从另一个线程中的 PipedWriter/PipeOutputStream 写入管道的数据。
    • 相应的也有不同类型的Writer/OutputStream输出流对应于不同的数据源:FileWriter/FileOutputStream,CharArrayWriter/ByteArrayOutputStream,StringWriter,PipeWriter/PipedOutputStream。
IO流的应用选择

确定选用流对象的步骤

  • 确定原始数据的格式
  • 确定是输入还是输出
  • 是否需要转换流
  • 数据的来源(去向)
  • 是否需要缓冲
  • 是否需要格式化输出
特殊需求
  • 从Stream转化为Reader,Writer:InputStreamReader,OutputStreamWriter
  • 对象输入输出流:ObjectInputStream,ObjectOutputStream
  • 进程间通信:PipeInputStream,PipeOutputStream,PipeReader,PipeWriter
  • 合并输入:SequenceInputStream
  • 更特殊的需要:PushbackInputStream, PushbackReader, LineNumberInputStream, LineNumberReader
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页