1. 注释解释:

  A character-stream reader that allows characters to be pushed back into the stream.

  一个允许字符被推回到流中的字符流读取器。(可能“推回”这个词不太准确)

  根据我们以往对输入流的的认知,它应该是单向的,被从头到尾依次读取。即使有些流 提供 mark 功能,那也是造成对某一部分的重复读取,不会产生流数据源本身不包含的字符。但是 PushbackReader 不一样,它允许调用者将一些数据源本身不包含的字符插入到流的任意位置,下面我们来看看实现原理。

2. 定义

  首先我们来看看它的定义和构造方法:

    

  可以看出,PushbackReader 继承自 FilterReader,查看过 FilterReader 源码,只是对 Reader 的一个通用包装类,没有什么特殊功能的添加(可能只是为了以后扩展)。而想要构造一个有意义 PushbackReader,必须向构造方法传递一个 Reader 实例(否则  ensureOpen  方法校验不通过),构造方法会初始化一个回退缓冲区和缓冲区位置指针,这两个便是 PushbackReader 的关键字段了。

3. 核心方法

  3.1. read 方法

    

    

  可以看出,read 方法都会优先从缓冲区读取数据。其中,缓冲区 pos 指针在最后表示缓冲区没有数据了。那么缓冲区的数据哪里来的呢?下面看看 unread 方法。

  3.2. unread 方法

    unread 方法就是该类最核心的方法了,它允许调用者通过该方法将数据填充到缓冲区,然后在 read 时被优先读取。

    

    

    可以看出,unread 方法将数据从缓冲区的后面向前面填充到缓冲区,然后 read 从前向后读取,类似一个栈结构。但是注意,单次回推的字符序列并不会逆序,而是作为一个整体。所以 unread 和 read 并不是一个简单的逆序过程。

4. 总结

  4.1. PushbackReader 提供 unread 方法,允许使用者将自定义的数据插入到输入流中;

  4.2. 插入的数据被保存在缓冲区中,一旦缓冲区中有数据插入,那么下次读取将会优先读取缓冲区;

  4.3. 后插入的数据,先读取(但单次插入的并不会被逆序);

5. 举例

  假如输入流源数据为字符串 “123456789”,那么当读取 “123” 之后分别执行 unread 推回这几个串:“abc”、“de”、“fghi”,那么最终读取完成后的结果就是 “123fghideabc456789” 。

6. 验证

  下面我们来编写代码测试一下,为了简单起见我把被包装的 Reader 类使用 StringReader :

    

public class PushbackReaderTest {
public static void main(String[] args) throws IOException {
StringReader stringReader = new StringReader("123456789");
PushbackReader pushbackReader = new PushbackReader(stringReader, 100);
StringBuilder stringBuilder = new StringBuilder();
char[] buff = new char[100];
//第一步,首先读取 “123”
int n = pushbackReader.read(buff, 0, 3);
stringBuilder.append(buff);
System.out.println("第一步,读取了 " + n + " 个字符:");
System.out.println(buff);
//第二步,unread:abc, de, fghi
pushbackReader.unread(new char[]{'a', 'b', 'c'});
pushbackReader.unread(new char[]{'d', 'e'});
pushbackReader.unread(new char[]{'f', 'g', 'h', 'i'});
int c = 0;
while (c != -1){
c = pushbackReader.read();
stringBuilder.append((char) c);
}
System.out.println("最终读取的数据:" + stringBuilder.toString());
}
}

  测试结果:

    

javaIO——PushbackReader的更多相关文章

  1. [二十三]JavaIO之PushbackReader

      功能简介   PushBackReader允许将字符推回到流的字符流 reader   PushBackReader 是一个装饰器模式最寻常的样子FilterReader 是抽象的装饰器模式 De ...

  2. [三]JavaIO之IO体系类整体设计思路 流的概念以及四大基础分类

    从本文开始,将正式进入JavaIO的简介 在继续javaIO系列的文章之前 可以过去看一下 本人博客上的设计模式中的 适配器模式和装饰器模式 这会对接下来的阅读大有帮助   本文是从逻辑上介绍整个的J ...

  3. [四] JavaIO之类层次体系结构横向比对

      IO家族类层次体系结构横向匹配   上一篇文章中主要介绍了JavaIO流家族的整体设计思路,简单回顾下 基本逻辑涉及数据源 流的方向,以及流的数据形式这三个部分的组合 按照流的数据形式和流的方向, ...

  4. [二十六]JavaIO之再回首恍然(如梦? 大悟?)

    流分类回顾 本文是JavaIO告一段落的总结帖 希望对JavaIO做一个基础性的总结(不涉及NIO) 从实现的角度进行简单的介绍 下面的这两个表格,之前出现过 数据源形式 InputStream Ou ...

  5. javaIO -- 流的体系设计思路、基础分类

    一.流 1. 流的含义 在程序设计中,流是对于数据流动传输的一种抽象描述任何有能力产出数据的数据源,或者有能力接受数据的接收端对象都是一个流. 2. 流的源和目的 数据可能从本地文件读取,或者写入,  ...

  6. JavaIO学习笔记(五)

    JavaIO前期准备 什么是同步 指的是用户进程触发IO操作并等待或者轮询的去查看IO操作是否就绪 什么是异步 异步是指用户进程触发IO操作以后便开始做自己的事情,而当IO操作已经完成的时候会得到IO ...

  7. javaIO系统----再看装饰者模式

    javaIO系统拥有各种各样的类,尤其是每次要进行读写操作时,总会一层套一层的new,以前不明白为什么要这样做,不过学习了适配器模式后,对于这种做法立刻了解了:动态扩展IO的功能,使之符合使用者的习惯 ...

  8. Java学习日记之 Java-IO流

    Java中的IO流在处理上分为字节流和字符流.字节流和字符流的区别 : 1.字节流读取的时候,读到一个字节就返回一个字节:  字符流使用了字节流读到一个或多个字节(中文对应的字节数是两个,在UTF-8 ...

  9. javaIO框架小析

    IO即数据读写.数据是应用的中心要素,而数据读写的能力和可扩展性是编程平台的基础支撑. 概念框架 方式: 字节流 Byte 和 字符流 Char 方向: 输入 Input 和 输出 Output : ...

随机推荐

  1. DELPHI安卓动态权限申请

    DELPHI安卓动态权限申请 安卓8.0以前的版本,只需要给静态权限就可以了,但安卓8.0及以后的版本,还需要运行期用代码动态申请权限. 下面以<蓝牙权限>为例,其他权限类似. Delph ...

  2. Xshell登录Vagrant方式

    Xshell登录Vagrant方式 我上一篇文章 介绍了vagrant 如何创建虚拟机集群,在上篇文章的基础上,用xshell 登录 虚拟机发现 默认是无法使用账号密码登录root账号,只能使用vag ...

  3. InsetDrawable

    表示把一个Drawable嵌入到另外一个Drawable的内部,并且在内部留一些间距, 类似与Drawable的padding属性,但padding表示的是Drawable的内容与Drawable本身 ...

  4. Windows10 64位 安装 Docker

    本文主要介绍Docker在Windows下的安装.关于Docker的介绍和文档在其官网中可以找到:http://www.docker.com .安装环境:Windows10 64位. Docker引擎 ...

  5. delphi7 clientdataset 详解

    delphi Midas SQLServer的自增字段的处理1.新增时,表中有自增字段,但是不希望用Refresh,直接ApplyUpdates直接看见自增字段的值在DataSetProvider.A ...

  6. python内置数据结构

    数据类型: 数值型 int float complex bool 序列对象 字符串 str 列表 list 元组 tuple 键值对 集合 set 字典dict 数值型: int.float.comp ...

  7. mvn安装

    先安装jdk.jre,maven需要jdk.jre支持 1.安装 jdk 卸载自带jdk rpm -qa | grep jdk rpm -e --nodeps 下载 JDK JDK 下载地址:http ...

  8. python网络编程----requests模块

    python访问网站可以用标准模块--urllib模块(这里省略),和requests(安装-pip install requests)模块,requests模块是在urllib的基础上进行的封装,比 ...

  9. 基于c开发的全命令行音频播放器

    cmus是一个内置了音频播放器的强大的音乐文件管理器.用它的基于ncurses的命令行界面,你可以浏览你的音乐库,并从播放列表或队列中播放音乐,这一切都是在命令行下. Linux上安装cmus 首先, ...

  10. 【ARM-Linux开发】wubi.exe安装Ubuntu14.04出现为/检查磁盘时发生严重错误的解决方法

    原文:http://jingyan.baidu.com/article/0aa22375bbffbe88cc0d6419.html 我写过一篇叫做 如何硬盘装麒麟系统 的经验,介绍了如何不使用优盘的情 ...