java io -- InputStream

上篇文章java io-流简单介绍了流的概念,本文我们就关注于字节流。

java字节流说起,java的字节流有两种:输入流和输出流,我这里只分析输入流,输出流与输入流类似,只是方向相反。

输入流,顾名思义,就是我们输入我们程序的字节流,也就是如果我们的程序需要输入时,我们从流中读取。

输入流是一个抽象的概念,当我们读取文件时,就把文件抽象成一个输入流,当我们读取字节数组时,可以把这个字节数组当成输入流,当我们从网络读取数据时,可以把socket当成一个输入流(网络流这里只是提及,本文暂不涉及,会在网络部分讲述)。

我的习惯,废话少说,先上类图。


图1 InputStream类图


1是输入流的整体类图,由于我们日常用到的输入流就是那么几个,所以如果有遗漏,还请参照oracle官网。

从类图中可以看出,InputStream算是一个top class,首先需要注意的是这个类是一个抽象类。为了能够更好的理解输入流,我先给大家展示一下InputStream的定义和结构。

public abstract class InputStream implements Closeable {
 .......
// 方法的定义见下图
}

图2 InputStream类 结构


好的,从上面的代码和图中,得知Inputstream是一个抽象类,现在我们深入几个重要的方法,进行探究。

1 read()

public abstract int read() throws IOException;

read()函数,这就是这个类的 灵魂函数了,作为一个输入流,最重要的就是读!

jdk中的源码中,有read方法很详细的注释。

这个方法用来读取inputstream中的下一个字节!如果没有数据返回-1,如果有,就以int的方式返回,为什么返回一个int呢?以为一个字节一共8bit,用数字0-255就可以表示,深入一点呢,就是一个int共四个字节,用来放这读取出来的一个字节必然是够了。

而且还有一点需要强调,在java的注释中,有这么一句:

// This method blocks until input data is available

也就是说,这个方法是一个block的方法,如果你正在看java的nio或java的socket,就会知道,这个block是一个很重要的特性。当然如果你只是读读文件,可以先不用理会这个特性。

read()方法是一个抽象方法,这些特性其实也只是规定罢了,真正的实现都是要在子类中实现的,我们之后再说。


2 read(byte b[], int off, int len)

这个方法的源码如下:

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


从上述源码中,我得出如下几点结论

1)这个read()方法是一个重要的方法,在我们的实际工作中,不可能是一个字节一个字节去读取,一定是一次读取一批,这时,java为我们封装了一个读取多个字节的方法,从源码中可以看出,这个方法其实也时循环去读取数据。

2)这是一个非抽象方法,InputStream的子类可以直接调用这个方法,我个人认为这算是一个template模式

3)这个方法的参数是指从流中欲读取len长的数据,置于以offset开头的数组中。

如果读取流到达末端,即时返回。最后返回的是实际从流中读取的数据长度。

4)这个方法有个需要注意的地方:

如果数组的长度不够,会报IndexOutOfBoundsException异常。


3 read( byte  b[]

这个方法源码如下:

public int read(byte b[]) throws IOException {
    return read(b, 0, b.length);
}

这个方法是从流中读取数据,直接读满这个数组(如果流中有足够的数据),并返回实际读取的字节数。

好的,InputStream说了这么多,应该对字节流有了一个起码的认识了,由于输入流是一个整体的抽象,一个文件可以作为一个字节流,一个字节数组也可以作为一个字节流。因此java对每一种输入流都做了一个子类,比如ByteArrayInputStream就可以把一个字节数组作为一个输入流,当然了这个字节数组一定是在内存中了。

如果想读取磁盘中的文件,这时就需要一个FileInputStream了,由于在日常的开发中,读取文件是常有的事,因此我们下一节就对FileInputStream做一个介绍。

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值