接着上篇文章,本篇继续说java.io包中的字节流。按照前篇文章所说,java.io包中的字节流中的类关系有用到GoF《设计模式》中的装饰者模式,而这正体现在FilterInputStream和FilterOutputStream和它的子类上,我们这篇就来看一看。

0. FilterInputStream和FilterOutputStream

首先,这两个都分别是InputStream和OutputStream的子类。而且,FilterInputStream和FilterOutputStream是具体的子类,实现了InputStream和OutputStream这两个抽象类中为给出实现的方法。

但是,FilterInputStream和FilterOutputStream仅仅是“装饰者模式”封装的开始,它们在各个方法中的实现都是最基本的实现,都是基于构造方法中传入参数封装的InputStream和OutputStream的原始对象。

比如,在FilterInputStream类中,封装了这样一个属性:

1
protected volatile InputStream in;

而对应的构造方法是:

1
2
3
protected FilterInputStream(InputStream in) {
    this.in = in;
}

read()方法的实现则为:

1
2
3
public int read() throws IOException {
    return in.read();
}

其它方法的实现,以及FilterOutputStream也都是同理类似的。

我们注意到FilterInputStream和FilterOutputStream并没给出其它额外的功能实现,只是做了一层简单地封装。那么实现额外功能的实际是FilterInputStream和FilterOutputStream的各个子类。

1. BufferedInputStream/BufferedOutputStream

先说说这个最简单的一对,BufferedInputStream和BufferedOutputStream。顾名思义,Buffered就是缓 冲了的。在BufferedInputStream和BufferedOutputStream中,都额外实现了byte数组做buffer。

我们知道在父类FilterInputStream和FilterOutputStream类中,已经在构造方法时封装了原始的InputStream或者OutputStream对象。

在我们使用BufferedInputStream和BufferedOutputStream来进行read()和write()调用的时候,并不一定直接对封装的InputStream或者OutputStream对象进行操作,而是要经过缓冲处理。

在BufferedInputStream的read()中,实际上是一次读取了多个字节到缓冲数组,而非一次只读取一个。后续的read()操作 可以直接从数组中获取字节,而不必再次调用封装的InputStream对象的read()操作。这样做其实在一定情况下可以减少底层的read调用次 数,降低成本开销,提高了效率。

在BufferedOutputStream中也是一样,它的write()会先把数据写到缓冲数组中,直到数据达到了某个特定的限额,再调用write()的时候回真正调用到封装的OutputStream对象的write()方法。

2. DataInputStream/DataOutputStream

这也是比较重要的一对Filter实现。那么说起功能,实际上就不得不提到他们除了extends FilterInputStream/FilterOutputStream外,还额外实现了DataInput和DataOutput接口。

我们可以先来看下DataInput和DataOutput这两个interface。

DataInput接口的outline

再看DataOutput:

DataOutput接口的outline

而DataInputStream/DataOutputStream这一对实际上所做的也就是这两个接口所定义的方法。再 DataInputStream/DataOutputStream中,这些方法做了拼接和拆分字节的工作。通过这些方法,我们可以方便的读取、写出各种 我们实际所面对的类型的数据,而不必具体去在字节层面上做细节操作。

3. PrintStream

这个类不成对,只有这样一个OutputStream。看起名字中的Print,我们会想到什么?println()方法和print()方法。实 际上,包括java.lang包中的System.out和System.error,使用的都是PrintStream类对象。

从使用层面来看,这个类主要是提供了丰富的print()和println()的各类参数重载方法。对各个类型的输出,包括换行处理等都集成在内。还有format()方法,帮我们做到了类似C语言中printf()函数的效果。

而从实现上来看,这些print()和println()最终都调用了各类write()方法。在这些write()方法中,实际上使用到了类中封装的这两个属性。

1
2
private BufferedWriter textOut;
private OutputStreamWriter charOut;

他们都是Writer的子类,是字符流处理类,有编码解码机制,我们会在后续文章中详细说明。

4. PushbackInputStream

此类增加了“回退(push back)”功能。在读完一部分数据之后,可以“回退”到之前读过的某个“位置”,并重新设置这些数据。

在实现上,类似于BufferedInputStream,在PushbackInputStream增加了缓冲数组,回退时调整数组的下标索引,并边回退边重置数据。

5. LineNumberInputStream

这个主要是方便读入时的行号处理,但已经被@Deprecated了,就不多说了。

java.io包中的字节流—— FilterInputStream和FilterOutputStream的更多相关文章

  1. 1.java.io包中定义了多个流类型来实现输入和输出功能,

    1.java.io包中定义了多个流类型来实现输入和输出功能,可以从不同的角度对其进行分 类,按功能分为:(C),如果为读取的内容进行处理后再输出,需要使用下列哪种流?(G)   A.输入流和输出流 B ...

  2. [19/03/29-星期五] IO技术_File(文件)类(可操作文件,不能操作其里边内容,位于Java.io 包中)&递归遍历

    一.概念 java.io.File类:代表文件和目录. 在开发中,读取文件.生成文件.删除文件.修改文件的属性时经常会用到本类. 以pathname为路径创建File对象,如果pathname是相对路 ...

  3. java.io包中的四个抽象类

    IO所谓的四大抽象类就是:  InputStream.OutputStream.Reader.Writer

  4. Java.io 包(字节流)

    I/O流概述 在 Java 中,把不同类型的输入.输出源抽象为流(Stream),而其中输入或输出的数据则称为数据流(Data Stream),用统一的接口表示,从而使程序设计简单明了.流是一组有顺序 ...

  5. Java:输入输出流 java.io包的层次结构

    1.什么是IO Java中I/O操作主要是指使用Java进行输入,输出操作. Java所有的I/O机制都是基于数据流进行输入输出,这些数据流表示了字符或者字节数据的流动序列.Java的I/O流提供了读 ...

  6. Java源码解析——Java IO包

    一.基础知识: 1. Java IO一般包含两个部分:1)java.io包中阻塞型IO:2)java.nio包中的非阻塞型IO,通常称为New IO.这里只考虑到java.io包中堵塞型IO: 2. ...

  7. Java IO流中的File类学习总结

    一.File类概述 File类位于java.io包中,是对文件系统中文件以及文件夹进行封装的对象,可以通过对象的思想来操作文件和文件夹. File类有多种重载的构造方法.File类保存文件或目录的各种 ...

  8. java.io包下适配和装饰模式的使用

    如java.io.LineNumberInputStream(deprecated),是装饰模式(decorate)的实现: 如java.io.OutputStreamWriter,是适配器模式(ad ...

  9. 黑马程序员——【Java基础】——File类、Properties集合、IO包中的其他类

    ---------- android培训.java培训.期待与您交流! ---------- 一.File类 (一)概述 1.File类:文件和目录路径名的抽象表现形式 2.作用: (1)用来将文件或 ...

随机推荐

  1. 浩瀚移动POS收银开单扫描解决方案PDA仓储系统,无线批发,移动批发,无线POS,无线销售APP-车销管理PDA

    适用范围 各种业态的批发商铺.批发市场.订货会.展销会.配送中心仓库…… 产品简介 随着移动技术与智能PDA设备的迅猛发展,中国已经跨步进入移动信息化社会.移动商务是移动信息社会的重要载体与形式,它开 ...

  2. TStringList 常用操作

    //TStringList 常用方法与属性: var   List: TStringList;   i: Integer; begin   List := TStringList.Create;   ...

  3. wpf,图片灰化处理

    private BitmapSource ToGray(BitmapSource source) { FormatConvertedBitmap re = new FormatConvertedBit ...

  4. ios 简单的倒计时验证码数秒过程实现

    timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerFireMethod:) ...

  5. Android 自动化测试—robotium(七) 使用Junit_report测试报告

    使用Robotium进行测试的时候,要想可以导出明了的测试结果,可以使用junitreport来实现 junit-report下载地址:https://github.com/jsankey/andro ...

  6. [转]HTML5本地存储——Web SQL Database

    在HTML5 WebStorage介绍了html5本地存储的Local Storage和Session Storage,这两个是以键值对存储的解决方案,存储少量数据结构很有用,但是对于大量结构化数据就 ...

  7. UVa1515 Pool construction(最小割)

    题目 Source https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_pr ...

  8. XIII Open Cup named after E.V. Pankratiev. GP of SPb

    A. Graph Coloring 答案为$1$很好判,为$2$只需要二分图染色,对于$3$,首先爆搜哪些边要染成第$3$种颜色,然后二分图染色判定即可. B. Decimal Fraction 枚举 ...

  9. hadoop2.2.0 + hbase 0.94 + hive 0.12 配置记录

    一开始用hadoop2.2.0 + hbase 0.96 + hive 0.12 ,基本全部都配好了.只有在hive中查询hbase的表出错.以直报如下错误: java.io.IOException: ...

  10. 使用TCMalloc优化OpenResty

    1.安装依赖包 yum -y install wget gcc gcc-c++ -y 2.安装libunwind库可以从http://ftp.twaren.net/Unix/NonGNU//libun ...