JDK源码(五):ByteArrayInputStream

本文深入解析了ByteArrayInputStream类,它是字节数组输入流,继承自InputStream。文章详细介绍了其内部结构,包括字节数组缓冲区、计数器、标记位置等,并提供了构造方法、read()、skip()等关键方法的实现原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        ByteArrayInputStream 是字节数组输入流。它继承于InputStream。

       它包含一个内部缓冲区,该缓冲区包含从流中读取的字节,它的内部缓冲区就是一个字节数组,而ByteArrayInputStream本质就是通过字节数组来实现的。

       我们都知道,InputStream通过read()向外提供接口,供它们来读取字节数据;而ByteArrayInputStream 的内部额外的定义了一个计数器,它被用来跟踪 read() 方法要读取的下一个字节。

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));
    }
}

类名


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;
}

更多精彩文章,请关注微信公众号:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

徐楠_01

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值