IOInputStream类型

举报
xcc-2022 发表于 2022/07/21 22:12:47 2022/07/21
【摘要】 从java字节流说起,java的字节流有两种:输入流和输出流,我这里只分析输入流,输出流与输入流类似,只是方向相反。输入流,顾名思义,就是我们输入我们程序的字节流,也就是如果我们的程序需要输入时,我们从流中读取。输入流是一个抽象的概念,当我们读取文件时,就把文件抽象成一个输入流,当我们读取字节数组时,可以把这个字节数组当成输入流,当我们从网络读取数据时,可以把socket当成一个输入流(网络...

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做一个介绍。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。