JDK源码:ByteArrayInputStream
Posted jdkSpring
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDK源码:ByteArrayInputStream相关的知识,希望对你有一定的参考价值。
ByteArrayInputStream 是字节数组输入流。它继承于InputStream。
它包含一个内部缓冲区,该缓冲区包含从流中读取的字节,它的内部缓冲区就是一个字节数组,而ByteArrayInputStream本质就是通过字节数组来实现的。
我们都知道,InputStream通过read()向外提供接口,供它们来读取字节数据;而ByteArrayInputStream 的内部额外的定义了一个计数器,它被用来跟踪 read() 方法要读取的下一个字节。
类名
public class ByteArrayInputStream extends InputStream
成员变量
/**
* 字节数组缓冲区。
* 元素buf[0]到buf[count-1]是唯一可以从流中读取的字节
* 元素buf[pos]是下一个要读取的字节
*/
protected byte buf[];
/**
* 从输入流缓冲区读取的下一个字符的索引。
* 此值应始终为非负且不大于count的值。
* 从输入流缓冲区读取的下一个字节将是buf[pos]。
*/
protected int pos;
/**
* 流中当前标记的位置。
* 在构造时,默认情况下,ByteArrayInputStream对象标记在位置0处。
* 它们可以用mark()方法标记在缓冲区内的另一个位置。
* 当前缓冲区位置由reset()方法设置到这一点。
* 如果未设置标记,则标记的值是传递给构造函数的偏移量(如果未提供偏移量,则为0).
*/
protected int mark = 0;
/**
* 一个大于输入流缓冲区中最后一个有效字符的索引。
* 此值应始终为非负且不大于buf的长度。
* 它比输入流缓冲区中最后一个字节的位置大一个
*/
protected int count;
方法
/**
* 创建ByteArrayInputStream,使用buf作为缓冲区数组。
* pos的初始值是0,count的初始值是buf的长度
*/
public ByteArrayInputStream(byte buf[])
/**
* @param buf 目标字节数组
* @param offset 要读取的第一个字节的缓冲区中的偏移量.
* @param length 从缓冲区读取的最大字节数。
*/
public ByteArrayInputStream(byte buf[], int offset, int length)
/**
* 从这个输入流中读取下一个字节的数据。
* 在0到255的范围内,返回值字节作为int型返回。
* 如果到达流的末尾而没有字节可用,则返回-1。
*/
public synchronized int read()
/**
* 从这个输入流将数据的字节读入一个字节数组。
* 如果pos等于count,则返回-1表示文件结束。
* 否则,读取的字节数avail等于len和count-pos中的较小者。
* 如果avail为正,则字节buf[pos]到buf[pos+avail-1]被复制到b[off]到b[off+avail-1]中,
* pos的值修改为pos+avail,并返回avail。
* @param b 目标字节数组.
* @param off 目标数组b中的起始偏移量
* @param len 读取的最大字节数.
* @return 读取到缓冲区中的字节总数,
* 如果由于已到达流的结尾而没有更多数据,则为-1。
*/
public synchronized int read(byte b[], int off, int len)
/**
* 跳过n个字符
*/
public synchronized long skip(long n)
/**
* 返回可从此输入流读取(或跳过)的剩余字节数。
*/
public synchronized int available()
//此方法只有一行代码:return true
public boolean markSupported()
/**
* 设置流中当前标记的位置。
* 在构造时,默认情况下,
* ByteArrayInputStream对象标记在位置0处。
* 可以用这种方法标记在缓冲区内的另一个位置
*/
public void mark(int readAheadLimit)
/**
* 将缓冲区重置到标记位置。
* 除非在构造函数中标记了另一个位置或指定了偏移量,
* 否则标记位置为0
*/
public synchronized void reset()
/**
* ByteArrayInputStream是基于内存Byte数组的流,
* 不需要close,当没有强引用的时候会自动被垃圾回收了,
* 所以close实现为空。
*/
public void close() throws IOException
read()
/**
* 从这个输入流中读取下一个字节的数据。
* 在0到255的范围内,返回值字节作为int型返回。
* 如果到达流的末尾而没有字节可用,则返回-1。
*/
public synchronized int read() {
return (pos < count) ? (buf[pos++] & 0xff) : -1;
}
read(byte b[], int off, int len)
/**
* 从这个输入流将数据的字节读入一个字节数组。
* 如果pos等于count,则返回-1表示文件结束。
* 否则,读取的字节数avail等于len和count-pos中的较小者。
* 如果avail为正,则字节buf[pos]到buf[pos+avail-1]被复制到b[off]到b[off+avail-1]中,
* pos的值修改为pos+avail,并返回avail。
* @param b 目标字节数组.
* @param off 目标数组b中的起始偏移量
* @param len 读取的最大字节数.
* @return 读取到缓冲区中的字节总数,
* 如果由于已到达流的结尾而没有更多数据,则为-1。
*/
public synchronized int read(byte b[], int off, int len) {
if (b == null) {
throw new NullPointerException();
} else if (off < 0 || len < 0 || len > b.length - off) {
throw new IndexOutOfBoundsException();
}
if (pos >= count) {
return -1;
}
//有效的可读长度
int avail = count - pos;
if (len > avail) {
len = avail;
}
if (len <= 0) {
return 0;
}
System.arraycopy(buf, pos, b, off, len);
pos += len;
return len;
}
skip(long n)
/**
* 跳过n个字符,k为实际跳过的字节
*/
public synchronized long skip(long n) {
long k = count - pos;
if (n < k) {
k = n < 0 ? 0 : n;
}
pos += k;
return k;
}
available()
/**
* 返回可从此输入流读取(或跳过)的剩余字节数。
*/
public synchronized int available() {
return count - pos;
}
mark(int readAheadLimit)
/**
* 设置流中当前标记的位置。
* 在构造时,默认情况下,
* ByteArrayInputStream对象标记在位置0处。
* 可以用这种方法标记在缓冲区内的另一个位置
*/
public void mark(int readAheadLimit) {
mark = pos;
}
reset()
/**
* 将缓冲区重置到标记位置。
* 除非在构造函数中标记了另一个位置或指定了偏移量,
* 否则标记位置为0
*/
public synchronized void reset() {
pos = mark;
}
代码注释
public class ByteArrayInputStream extends InputStream {
/**
* 字节数组缓冲区。
* 元素buf[0]到buf[count-1]是唯一可以从流中读取的字节
* 元素buf[pos]是下一个要读取的字节
*/
protected byte buf[];
/**
* 从输入流缓冲区读取的下一个字符的索引。
* 此值应始终为非负且不大于count的值。
* 从输入流缓冲区读取的下一个字节将是buf[pos]。
*/
protected int pos;
/**
* 流中当前标记的位置。
* 在构造时,默认情况下,ByteArrayInputStream对象标记在位置0处。
* 它们可以用mark()方法标记在缓冲区内的另一个位置。
* 当前缓冲区位置由reset()方法设置到这一点。
* 如果未设置标记,则标记的值是传递给构造函数的偏移量(如果未提供偏移量,则为0).
*
* @since JDK1.1
*/
protected int mark = 0;
/**
* 一个大于输入流缓冲区中最后一个有效字符的索引。
* 此值应始终为非负且不大于buf的长度。
* 它比输入流缓冲区中最后一个字节的位置大一个
*/
protected int count;
/**
* 创建ByteArrayInputStream,使用buf作为缓冲区数组。
* pos的初始值是0,count的初始值是buf的长度
*/
public ByteArrayInputStream(byte buf[]) {
this.buf = buf;
this.pos = 0;
this.count = buf.length;
}
/**
* @param buf 目标字节数组
* @param offset 要读取的第一个字节的缓冲区中的偏移量.
* @param length 从缓冲区读取的最大字节数。
*/
public ByteArrayInputStream(byte buf[], int offset, int length) {
this.buf = buf;
this.pos = offset;
this.count = Math.min(offset + length, buf.length);
this.mark = offset;
}
/**
* 从这个输入流中读取下一个字节的数据。
* 在0到255的范围内,返回值字节作为int型返回。
* 如果到达流的末尾而没有字节可用,则返回-1。
*/
public synchronized int read() {
return (pos < count) ? (buf[pos++] & 0xff) : -1;
}
/**
* 从这个输入流将数据的字节读入一个字节数组。
* 如果pos等于count,则返回-1表示文件结束。
* 否则,读取的字节数avail等于len和count-pos中的较小者。
* 如果avail为正,则字节buf[pos]到buf[pos+avail-1]被复制到b[off]到b[off+avail-1]中,
* pos的值修改为pos+avail,并返回avail。
* @param b 目标字节数组.
* @param off 目标数组b中的起始偏移量
* @param len 读取的最大字节数.
* @return 读取到缓冲区中的字节总数,
* 如果由于已到达流的结尾而没有更多数据,则为-1。
*/
public synchronized int read(byte b[], int off, int len) {
if (b == null) {
throw new NullPointerException();
} else if (off < 0 || len < 0 || len > b.length - off) {
throw new IndexOutOfBoundsException();
}
if (pos >= count) {
return -1;
}
//有效的可读长度
int avail = count - pos;
if (len > avail) {
len = avail;
}
if (len <= 0) {
return 0;
}
System.arraycopy(buf, pos, b, off, len);
pos += len;
return len;
}
/**
* 跳过n个字符
*/
public synchronized long skip(long n) {
long k = count - pos;
if (n < k) {
k = n < 0 ? 0 : n;
}
pos += k;
return k;
}
/**
* 返回可从此输入流读取(或跳过)的剩余字节数。
*/
public synchronized int available() {
return count - pos;
}
public boolean markSupported() {
return true;
}
/**
* 设置流中当前标记的位置。
* 在构造时,默认情况下,
* ByteArrayInputStream对象标记在位置0处。
* 可以用这种方法标记在缓冲区内的另一个位置
*/
public void mark(int readAheadLimit) {
mark = pos;
}
/**
* 将缓冲区重置到标记位置。
* 除非在构造函数中标记了另一个位置或指定了偏移量,
* 否则标记位置为0
*/
public synchronized void reset() {
pos = mark;
}
/**
* ByteArrayInputStream是基于内存Byte数组的流,
* 不需要close,当没有强引用的时候会自动被垃圾回收了,
* 所以close实现为空。
*/
public void close() throws IOException {
}
}
案例
public class ByteArrayInputStreamDemo {
public static void main(String[] args) {
ByteArrayInputStream bais=null;
StringBuilder sb=new StringBuilder();
int temp=0;
int num=0;
long date1=System.currentTimeMillis();
try{
byte[] b="abcdefghijklmnopqstuvxyz".getBytes();
//从字符数组b中读取数据,从下标为2开始计数读8个
bais=new ByteArrayInputStream(b,2,8);
while((temp=bais.read())!=-1){
sb.append((char)temp);
num++;
}
System.out.println(sb);
System.out.println("读取的字节数:"+num);
}finally{
try{
bais.close();//不需要关闭流的,但是调用close没有任何影响,close不做任何事情
}catch(IOException e){
e.printStackTrace();
}
}
long date2=System.currentTimeMillis();
System.out.println("耗时:"+(date2-date1));
}
}
以上是关于JDK源码:ByteArrayInputStream的主要内容,如果未能解决你的问题,请参考以下文章