2.1.JavaIO类库的基本架构

前言

小伙汁,你学这章,得有基础的操作系统知识,当然这篇不用,如果缺了补一补再看,免得云里雾里

概述

​ Java 的I/O操作类在包java.io下,大概有将近80个类,这些类大概可以分为如下4组:

  • 基于字节操作的I/O接口:InputStream 和 OutputStream [数据格式]

  • 基于字符操作的I/O接口:Writer 和 Reader [数据格式]

  • 基于磁盘操作的I/O接口:File [传输方式]

  • 基于网络操作的I/O接口:Socket [传输方式]

    说明:前两组主要是传输数据的数据格式,后两组主要是传输数据的方式。(虽然Socket类不在java.io包下,但是为了方便说明,就放在一起)

    个人认为I/O的核心问题就两点:

    数据格式&传输方式,也就是一个将什么样的数据,传到什么地方去,的问题。

    对于人机交互,除了交互功能以外,我们就应该尽力去提升交互效率,而数据格式&传输方式是影响效率最关键的因素,我们将通过这两点展开。

基于字节的I/O操作接口

基于字节的I/O操作接口,输入和输出是InputStream 和 OutputStream,下图是他们的类层次结构图:
在这里插入图片描述

以输入流为例,根据数据类型操作方式又被划分,如FileInputStream等,每个子类处理不同的操作类型。

有两点要说明一下:
  • 操作数据的方式是可以组合使用的,不冲突:

    OutputStream out = new BufferedOutputStream(new ObjectOutputStream(new FileOutputStream("filename")));
    
  • 必须要指定流最终写到什么地方,磁盘 or 网络?(实际上网络也相当于一种文件)

基于字符的I/O操作接口

无论磁盘or网络传输,最小的存储单元都是字节!字节!字节!(重要的事情说三遍),而不是字符,为了操作方便,当然要提供一个字符的I/O啦!

基于字符的I/O操作接口,输入和输出是Reader 和 Writer,下图是他们的类层次结构图:
在这里插入图片描述
其中,Writer 类提供了一个抽象方法 write(char cbuf[], int off, int len), 交由子类去实现;同样的,Reader类有int read(char cbuf[], int off, int len),返回读到的 n 个字节数。

但是!!!不管是 Writer 还是 Reader 类,它们都只定义了怎么写or读,但是并没有规定数据要写到哪去,这些就是和基于磁盘和网络的工作机制有关了。

字节流和字符流的区别(解惑)
  • 1.字节流读取的时候,读到一个字节就返回一个字节; 字符流使用了字节流读到一个或多个字节(中文对应的字节数是两个,在UTF-8码表中是3个字节)时。先去查指定的编码表,将查到的字符返回。

    字节:读1返1;字符:读后先查表,再返回
  • 2.字节流可以处理所有类型数据,如:图片,MP3,AVI视频文件,而字符流只能处理字符数据。只要是处理纯文本数据,就要优先考虑使用字符流,除此之外都用字节流。

    字节流:所有类型无脑读;字符流:有表的就能处理,且优先考虑

字节与字符的转化接口

另外数据持久化or网络传输,都是以字节进行的,所以必须要有转化。其中读的转化过程如下图所示:
在这里插入图片描述

InputStreamReader 类是字节到字符的转化桥梁,InputStream 到 Reader 的过程要指定编码字符集,否则将采用操作系统默认字符集,很可能会出现乱码问题。StreamDecoder 正是完成字节到字符的解码的实现类。也就是当你用如下方式读取一个文件时:

try { 
           StringBuffer str = new StringBuffer(); 
           char[] buf = new char[1024]; 
           FileReader f = new FileReader("file"); 
           while(f.read(buf)>0){ 
               str.append(buf); 
           } 
           str.toString(); 
} catch (IOException e) {}

FileReader 类就是按照上面的工作方式读取文件的,FileReader 是继承了 InputStreamReader 类,实际上是读取文件流,然后通过 StreamDecoder 解码成 char,只不过这里的解码字符集是默认字符集。

写入也是类似的过程,通过 OutputStreamWriter 类完成,字符–>字节的编码过程,由 StreamEncoder 完成。如下图所示:

在这里插入图片描述

几种常见的流

转换流(上面已经隆重的介绍过了)
  • InputStreamReader 是字节流–>字符流
  • OutputStreamWriter 是字符流–>字节流
  • 转换流可以将字节转成字符,原因在于,将获取到的字节通过查编码表获取到指定对应字符。 转换流的最强功能就是基于 字节流 + 编码表 。没有转换,没有字符流。
打印流
  • PrintWriter

  • PrintStream

    注打印流: A:只操作目的地,不操作数据源 B:可以操作任意类型的数据 C:如果启用了自动刷新,在调用println(),printf(),format()方法的时候,能够换行并刷新 D:可以直接操作文件

序列化流(啥,你不知道什么叫序列化?)
  • ObjectOutputStream序列化流

  • ObjectInputStream反序列化流

    序列化:把对象作为一个整体按照流一样的方式传输or存储

    反序列化:把网络中的流数据或者文件中的流数据还原成对象

    主要方法有:

  • Object readObject();该方法抛出异常:ClassNotFountException。

  • void writeObject(Object):被写入的对象必须实现一个接口:Serializable,否则就会抛出:NotSerializableException

法抛出异常:ClassNotFountException。

  • void writeObject(Object):被写入的对象必须实现一个接口:Serializable,否则就会抛出:NotSerializableException

  • 如果实现了该接口,想解决黄线问题就生成一个随机的serialVersionUID号码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值