java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > JavaI/O深入学习 输入和输出

JavaI/O深入学习之输入和输出

作者:木瓜芒果

这篇文章主要介绍了JavaI/O深入学习之输入和输出,Java类库中的I/O类分成输入和输出两部分,可以在JDK文档里的类层次结构中查看到。,需要的朋友可以参考下

前言

编程语言的I/O类库中常使用流这个抽象概念,它代表任何有能力产出数据的数据源对象或者是有能力接收数据的接收端对象。“流”屏蔽了实际的I/O设备中处理数据的细节。

在文章:<<Java I/O深入学习之File和RandomAccessFile>>中,我们讲到RandomAccessFile可以写入和读取文件,具备I/O功能,但是其只能针对文件,而I/O还涉及到很多其他场景比如网络、读取内存中的字符串等,所以Java类库中提供了一系列的类库来对其进行支持,也就是本文要总结学习的。

Java类库中的I/O类分成输入和输出两部分,可以在JDK文档里的类层次结构中查看到。通过继承,任何自Inputstream或Reader派生而来的类都含有名为read()的基本方法,用于读取单个字节或者字节数组。同样,任何自OutputStream或Writer派生而来的类都含有名为write()的基本方法,用于写单个字节或者字节数组。

但是,我们通常不会用到这些方法,它们之所以存在是因为别的类可以使用它们,以便提供更有用的接口。因此,我们很少使用单一的类来创建流对象,而是通过叠合多个对象来提供所期望的功能(这是装饰器设计模式的应用,也有专门写文总结过:装饰器模式)。实际上,Java中“流”类库让人迷惑的主要原因就在于:创建单一的结果流,却需要创建多个对象。

I/O需要应对的场景往往是多样化的,Java类库的设计者则是通过创建大量的类来解决这个难题,区区一篇文章难以详述,本文也只是尽力对传统I/O类库所涉及到的类提供一个总览,在把握整个脉络的前提下才能更好的理解并应用I/O类库来解决实际编程问题。如需涉及到细节,还是需要参考JDK文档。

1. InputStream/OutputStream

Java 1.0中,类库的设计者首先限定与输入有关的所有类都应该从InputStream继承,而与输出有关的所有类都应该从OutputStream继承。

1.1 InputStream

InputStream的作用是用来表示那些从不同数据源产生输入的类。这些数据源包括:

每一种数据源都有相应的InputStream子类,作为基础构件:

1.2 OutputStream

OutputStream的作用是表示那些可以输出到不同数据源的类,其具体的子类决定了输出所要去往的目标:字节数组、文件或管道,同样是作为基础构件:

1.3 装饰器

除了有上面的基础构件,还有两个子类:FilterInputStream/FilterOutputStream,也是InputStream和OutputStream的子类,它们为“装饰器”(decorator)类提供基类,其中,“装饰器”类可以把属性或有用的接口与基础构件连接在一起。因为上面提到的InputStream/OutputStream是单字节为单位来操作的,而真实的I/O场景远不止于此,所以就通过“装饰”(其原理是类之间的组合)的方式来扩展其功能。

我自己梳理了一下InputStream/OutputStream流继承层次结构,结合下面的解释来看可以对字节流体系有一个更清晰的认识:

1.3.1 FilterInputStream

FilterInputStream类主要有如下子类,也就是具体装饰器:

其提供的装饰功能主要在两个方面:

1.3.2 FilterOutputStream

与FilterInputStream类似,FilterOutputStream主要是完成写入的功能,主要有如下装饰器:

2. Writer/Reader

InputStream和OutputStream是提供面向字节形式的I/O,但是InputStream/OutputStream流继承层次结构仅支持8位字节流,并且不能很好地处理16位的Unicode字符。由于Unicode用于字符国际化(Java本身的char也是16位的Unicode),所以添加Reader/Writer继承层次结构就是为了在所有的I/O操作中都支持Unicode。

几乎所有原始的Java I/O流类都有相应的Reader和Writer类来提供天然的Unicode操作,我们可以对比一下:

我们发现大体上,这两个不同的继承层次结构中的接口即使不能完全相同,但是也是非常相似的。

对于InputStream和OutputStream来说,我们会使用FilterInputStream和FilterOutputStream的装饰器子类来修改“流”以满足特殊需要。Reader/Writer的类继承层次结构继续沿用相同的思想,但是又并不完全采用上面说到的装饰器模式。如下是自己梳理的Reader/Writer继承层次结构:

与前面的I/O继承层次结构图相对比可以发现,尽管BufferedOutputStream是FilterOutputStream的子类,但是BufferedWriter并不是FilterWriter的子类(FilterWriter是抽象类,但是没有任何子类,仅仅是作为一个占位符)。

2.1 适配器

有时我们必须把来自于“字节”层次结构中的类和“字符”层次结构中的类结合起来使用。为了实现这个目的,要用到“适配器”(adapter)类:InputStreamReader可以把InputStream转换为Reader,而OutputStreamWriter可以把OutputStream转换为Writer。

3. 总结

本文主要是梳理了传统I/O流的类继承层次结构,包括字节流(InputStream/OutputStream)和字符流(Writer/Reader),并没有一开始就一头扎进I/O类库的海洋中,主要是希望通过这种方式能够对整个I/O体系有一个清晰的认识,这对于进一步的学习可以有更明确的指导作用,下文会针对一些I/O的的典型使用方式进行总结。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文