Java I/O——InputStream


1. InputStream源码

public abstract class InputStream implements Closeable {

    // MAX_SKIP_BUFFER_SIZE is used to determine the maximum buffer size to
    // use when skipping.
    private static final int MAX_SKIP_BUFFER_SIZE = 2048;

//读取输入流的下一个字节,返回0-255,即字节大小;如果读完了,即没有下一个字节,返回-1;因此该方法可以用于检测是否读取到了输入流的末尾
//该方法会阻塞直到读到输入流的末尾或发生异常,如果发生错误,则抛出IOException异常
    public abstract int read() throws IOException; 

//读取输入流并存入缓冲数组b中,如果b的大小为0,则读取了0字节,返回0;如果因为达到输入流的末尾,没有字节可以读入,则返回-1;
    //其他情况,则至少读取1个字节并存在在b中,返回读取的字节个数,数组元素的值存放的是读取的字节大小
    //只要第一个字节不能读取(而不是最后一个)或者输入关闭,或者是发生其他错误,则抛出 IOException
    //如果b为空,则抛出 NullPointerException
    public int read(byte b[]) throws IOException {
        return read(b, 0, b.length);
    }

//从输入流中读取len个字节,存放在b中,存放位置从b[off]开始,返回读取的字节数
    //实现该方法的思路是反复调用read()方法 
    public int read(byte b[], int off, int len) throws IOException {
        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;
        }

        int c = read();
        if (c == -1) {
            return -1;
        }
        b[off] = (byte)c;

        int i = 1;
        try {
            for (; i < len ; i++) {
                c = read();
                if (c == -1) {
                    break;
                }
                b[off + i] = (byte)c;
            }
        } catch (IOException ee) {
        }
        return i;
    }

//从输入流中跳过n个字节,返回实际实际跳过的字节数,注意返回是long型
    public long skip(long n) throws IOException {

        long remaining = n;
        int nr;

        if (n <= 0) { 
            return 0; //如果n为负,则返回0,表明跳过0个字节
        }

        int size = (int)Math.min(MAX_SKIP_BUFFER_SIZE, remaining); 
        byte[] skipBuffer = new byte[size];
        while (remaining > 0) {
            nr = read(skipBuffer, 0, (int)Math.min(size, remaining));
            if (nr < 0) {
                break;
            }
            remaining -= nr;
        }

        return n - remaining;
    }

public int available() throws IOException {
        return 0;
    }

//关闭输入流并释放相关资源
    public void close() throws IOException {}

//记录当前输入流的位置
    public synchronized void mark(int readlimit) {}

public synchronized void reset() throws IOException {
        throw new IOException("mark/reset not supported");
    }

public boolean markSupported() {
        return false;
    }

}
从源码可以看出,InputStream是个抽象类(因此所有子类必须实现其方法),继承Object类,实现了Closeable接口,主要有3个read()方法,后面两个读入流并存入缓冲数组的方法的本质上还是通过第一个read方法实现的。

出现阻塞的两种情况:一是一直读直到检测到达了输入流的末尾;另外则是抛出异常。

抛出IOException的情况:

(1)      任何原因导致的无法读取第一个字节(不包含到达输入流末尾的情况)

(2)    输入流被关闭

(3)    出现其他I/O错误

抛出NullPointerException的情况:

(1)    数组b为空

注:数组为空和长度为0是不一样的;数组为空代表是一个空引用,不占内存空间;而长度为0,表明是一个空数组,空数组也是一个对象,包含的元素个数为0,占用内存。

2. InputStream类型

InputStream的作用是根据不同数据源产生输入的类,每一种数据源对应相应的InputStream子类,数据源包括:字节数组、String对象、文件、管道、流序列、其他数据源,对应的子类分别为:

ByteArrayInputStream:将缓冲区的字节数组当做InputStream使用

StringBufferInputStream:将String转换成InputStream

FileInputStream:用于从文件读取信息

PipedInputStream:产生用于写入PipedOutput Stream的数据

SequenceInputStream:  将两个或多个InputStream对象转换成单一InputStream

FilterInputStream:抽象类,作为“装饰器”的接口。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值