IO之BIO

原创
2020/03/20 16:38
阅读数 172

概念:

IO就是in和out。

IO是任何编程语言都无法回避的问题,IO问题是整个人机交互的核心问题,IO是机器获取和交换信息的渠道,IO问题很容易引起性能瓶颈。

java的IO可以大概分为四大类:

  1. 基于字节操作的IO接口:InputStream和OutputStream。
  2. 基于字符操作的IO接口:Reader和Writer。
  3. 基于磁盘操作的IO接口:File。
  4. 基于网络操作的IO接口:Socket。

前面两组只要根据数据的格式,后面两组根据传输数据的传输方式。而影响IO性能的也就是这两个方面:数据的格式、传输的方式(存储的方式)。

特性:

  1. 先进先出,最先写进输出流的数据最先被输入流读取到。
  2. 顺序存取,可以一个接一个地往流中写入一串字节,读出时也将按写入顺序读出一串字节。不能随机访问中间的数据。
  3. 只读或只写,每个流只能是输入流或者输出流的一种,不能同时具备两种功能,输入流只能具备读功能,输出流只能具备写功能。在一个数据传输通道中,如果既要读又要写,则要分别提供两个流。

基于字节操作的IO接口:

基于字节操作的IO接口输入输出分别是InputStream和OutputStream。

输入流接口InputSream的继承关系是:

输入流根据类型和操作方式又被划分为几个子类,每个子类处理不同的类型,输出流与输入流相似。

继承InputStream的子类:

  1. ByteArrayInputStream:处理字节数组的类,允许将内存的缓冲区当做InputStream使用。
  2. StringBufferInputStram:将String转换成InputStream,内部实现用的是StringBuffer。
  3. FileInputStream:从文件中读取数据。
  4. PipedInputStream:从管道中读取数据。
  5. SequenceInputStream:将多个流对象转化为一个InputStream。
  6. FilterInputStream:装饰器类,为其他InputStream提供功能。
  7. ObjectInputStream:装饰流

输出流接口OutputStream的继承关系是:

根据类图可以看出,SocketOutputStream继承了FiileOutputStream,说明网络IO实际上也是写文件,只不过多了底层操作系统将数据传输到其他地方的步骤。

继承OutputStream的子类:

  1. OutputStream:是所有输出流的父类,是一个抽象类。
  2. ByteArrayOutputStream:向Byte数组中写入数据。
  3. FileOutputStream:向文件中写入数据。
  4. PipeOutputStram:向与其他线程公用的管道中写入数据。
  5. ObjectOutputStream:装饰流。
  6. FilterOutputStram:装饰器类,为其他OutputStream提供功能。

基于字符的IO操作接口:

不管是磁盘还是网络传输,最小的传输单元都是字节而不是字符,所以IO操作的都是字节而不是字符。但是我们程序中通常操作的都是字符数据,为了操作方便专门提供的基于字符的接口。字符的编码则是字符操作中最麻烦的问题。

字符输出类Writer提供了一个抽象方法write(char buf[],int off,int len)由子类去实现。相关类层次结构如下:

继承Writer类的子类:

  1. Writer:是所有输出字符流的父类,是一个抽象类。
  2. CharArrayWriter:向Char数组中写入数据。
  3. StringWriter:向String中写入数据。
  4. BufferedWriter:一个装饰器类,为Writer提供缓冲功能。
  5. OutputStreamWriter:是OutputStream转换到Writer的桥梁。

字符输入类Reader与输出类结构相似。层次结构如下:

Reader类同样提供了一个抽象方法int read(char buf,int off,int len)会返回读到的n个字节数。

继承Reader类的子类:

  1. Reader:是所有输入字符流的父类,抽象类。
  2. CharArrayReader:是从字符数组中读取数据。
  3. StringReader:从String中读取数据。
  4. PipedReader:从与其他线程公用的管道中读取数据。
  5. BufferedReader:装饰器类,为其他Reader提供缓冲功能。
  6. FilterReader:所有自定义具体装饰流的父类。其子类会增加功能。
  7. InputStramReader:是InputStram转换到Reader的桥梁。

Reader和Writer都只定义的读或者写数据的方式,就是怎么读怎么写,而磁盘还是网络就是从哪里读或者写到哪里去,就是另外一回事了。

对应的流:

可以看到输入流和输出流一般是对应的,从某个地方读出来,也就可以写到某个地方去。

只有个别几个流不对应:

  1. LineNumberInputStream:主要完成从流中读取数据时,会获得相应的行号,至于什么时候分行、在哪里分行由该类主动确定,并不是在原始文件中有一个行号。
  2. PushbackInputStream:查看最后一个字节,不满意就放入缓冲区。主要用于编译器的词法语法分析。
  3. ,SequenceInputStream:可以认为是一个工具类,可以将两个或者多个输入流当成一个输入流依次读取。
  4. StringBufferInputStream:已经被废弃。String应该属于字符流的范围。
  5. PrintStream:辅助流,主要用来向其他输出流中写入数据,或者FileInputStream。本身内部实现是带有缓冲的,是对其他流综合运用的一个工具。

字符流与字节流的其他:

转换:

使用转换流(InputStreamReader,OutputStramWriter),将字节流转换为字符流。

使用:

  1. 字节和字符之间需要转换动作时。
  2. 流操作的数据需要解码或编码操作时。

区别:

  1. 字节流没有缓冲区,直接输出,字符流是输出到缓冲区。
  2. 字节流不调用close()方法,就会直接输出信息,而字符流必须要close()后才会输出信息,如果要手动输出可以使用刷新方法flush()。
  3. 读写单位不同,字节流以一个字节为单位读取,字符流一般以一个字符即8个字节(8bit)为单位进行读取。也会根据码表映射字符一次读取多个字节。
  4. 处理对象不同,字节流可以处理所有类型的数据,字符流只能处理字符类型的数据。

纯文本数据优先使用字符流,其他均用字节流。

展开阅读全文
打赏
0
1 收藏
分享
加载中
赞,👍
我们是菜鸟物流技术部,目前极度缺人,大神有没有兴趣呢?
2020/03/20 17:08
回复
举报
你干嘛 每个写博客的人你都要发一个邀请 是在做广告吗?
2020/03/21 10:34
回复
举报
不是广告,我们在全员招聘,今年项目多人手不够
2020/03/21 20:16
回复
举报
更多评论
打赏
3 评论
1 收藏
0
分享
返回顶部
顶部