Java 学习笔记 - IO篇:可推回流 PushbackInputStream
Posted 笑虾
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 学习笔记 - IO篇:可推回流 PushbackInputStream相关的知识,希望对你有一定的参考价值。
Java 学习笔记 - IO篇:可推回流 PushbackInputStream
简介
- 封装一个
InputStream
并为其提供一个缓冲区
。
1.1. 缓冲区大小默认1 byte
。
1.2. 构造函数中可以设置缓冲区大小:PushbackInputStream(InputStream in, int size)
read
读取,unread
推回- 如果执行了
unread
则会把数据填进缓冲区
。
3.1. 下次读取先从缓冲区取。
3.2. 不足的再到底层流中去取。
虽然叫推回
但并没有限制
先read
再unread
。所以下面我先把缓冲区填满,再读。
测试代码
@Test
public void pushbackInputStreamTest() throws IOException
byte[] 笨笨 = 1,2,3,4,5,6,7,8,9,10;
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
PushbackInputStream pbis = new PushbackInputStream(bais, 10);
pbis.unread(笨笨, 0, 3);
pbis.unread(笨笨, 6, 3);
byte[] 笑虾1 = new byte[10];
int l1 = pbis.read(笑虾1, 0, 5);
byte[] 笑虾2 = new byte[10];
int l2 = pbis.read(笑虾2, 0, 8);
byte[] 笑虾3 = new byte[10];
int l3 = pbis.read(笑虾3, 0, 9);
System.out.println("读取了: "+l1); // 读取了: 5
System.out.println("读取了: "+l2); // 读取了: 8
System.out.println("读取了: "+l3); // 读取了: 3
unread
unread 示意图
- 缓冲区为
空
时,pos 等于buf.length
;缓冲区已满
时,pos 等于0
。 - 每次
unread
后pos
向左移,永远指向有数据区的开始索引。(因为read
时就pos
这里开始读) - 多次
unread
的数据是整块整块放进来的。第一次1,2,3
,第二次7,8,9
unread 源码
public void unread(byte[] b, int off, int len) throws IOException
// 检查:输入流如果为 null 抛异常 IOException("Stream closed");
ensureOpen();
// 要推进来的数据,超过缓冲区大小
if (len > pos)
throw new IOException("Push back buffer is full");
// 算出还剩余多少可推回空间
pos -= len;
// 把数据拷进缓冲区
System.arraycopy(b, off, buf, pos, len);
read
read 示意图
- 先取缓冲区。
- 再取底层流。
read 源码
public int read(byte[] b, int off, int len) throws IOException
/**
* 1. 检查:输入流如果为 null 抛异常 IOException("Stream closed");
* 2. 检测:数组 b 不能为 null
* 3. 检查:是否偏移量、长度 < 0,是否要读取的【长度】超过数组【可用空间】。
* 4. 如果长度为 0 直接返 0
*/
ensureOpen();
if (b == null)
throw new NullPointerException();
else if (off < 0 || len < 0 || len > b.length - off)
throw new IndexOutOfBoundsException();
else if (len == 0)
return 0;
/**
* 1. 缓冲区中可用数据长度 = 缓冲区长度 - 剩余缓冲空间
* pos: 推回缓冲区中的位置,将读取该位置的下一个字节。
* 缓冲区为空时,pos 等于 buf.length;缓冲区已满时,pos 等于 0。
* 2. 缓冲中有可用数据,先从缓冲区取。
* 取完更新 pos 位置;
* 偏移已取的数量,为下次读取作准备;
* 减掉已经取得数量,算出还需要取多少长度。
*/
int avail = buf.length - pos;
if (avail > 0)
if (len < avail)
avail = len;
System.arraycopy(buf, pos, b, off, avail);
pos += avail;
off += avail;
len -= avail;
/**
* 如果 len 大于 0 表示缓冲区的数据取完了,还差 len 个长度。
* 1. 从底层流继续取。
* 2. 如果底层流没数据返回 -1。算一下缓存区是不是有取到内容。如果有,返回其长度。
* 3. 如果 缓存区、底层流 都成功取过数据,则返回总长度。
*/
if (len > 0)
len = super.read(b, off, len);
if (len == -1)
return avail == 0 ? -1 : avail;
return avail + len;
return avail;
参考资料
笑虾 :Java 学习笔记 - IO篇:常见的【IO流Stream】以及相互关系
以上是关于Java 学习笔记 - IO篇:可推回流 PushbackInputStream的主要内容,如果未能解决你的问题,请参考以下文章
Java 学习笔记 - IO篇:对象流 ObjectInputStreamObjectOutputStream