InputStream 类实现关系

InputStream 抽象类
InputStream 类重要方法设计如下:
底层源码实现
梳理部分InputStream及其实现类的源码分析。
InputStream
InputStream抽象类源码如下:
总结下JDK9的更新点:
类 java.io.InputStream 中增加了新的方法来读取和复制 InputStream 中包含的数据。
readAllBytes
readNBytes
transferTo
read(byte[], int, int) 和 readNBytes(byte[], int, int)看似是实现的相同功能,为何会设计readNBytes方法呢
read(byte[], int, int)是尝试读到最多len个bytes,但是读取到的内容长度可能是小于len
readNBytes(byte[], int, int) 会一直(while循环)查找直到stream尾为止
举个例子:如果文本内容是12345<end>, read(s,0,10)是允许返回123的, 而readNbytes(s,0,10)会一直(while循环)查找直到stream尾为止,并返回12345
read方法详解
在Java8中,InputStream被定义为一个抽象类,相应的,该类下的read()方法也是一个抽象方法,这也就意味着必须有一个类继承InputStream并且实现这个read方法。
但是在这三个方法中,只有参数列表为空的read方法定义为抽象方法,这也就意味着在直接继承自InputStream的所有子类中,必须重写这个方法.
read() 首先我们来看这个没有参数的read方法,从(来源)输入流中(读取的内容)读取数据的下一个字节到(去处)java程序内部中,返回值为0到255的int类型的值,返回值为字符的ASCII值(如a就返回97,n就返回110)。如果没有可用的字节,因为已经到达流的末尾,返回值 -1,运行一次只读一个字节,所以经常与while((len = inputstream.read()) != -1)一起使用
read(byte [] b ) 从(来源)输入流中(读取的内容)读取的一定数量字节数,并将它们存储到(去处)缓冲区数组b中,返回值为实际读取的字节数,运行一次读取一定的数量的字节数。java会尽可能的读取b个字节,但也有可能读取少于b的字节数。至少读取一个字节,第一个字节存储读入元素b[0],下一个b[1],等等。读取的字节数是最多等于b的长度。如果没有可用的字节,因为已经到达流的末尾,返回值-1,如果b.length==0,则返回0
read( byte [] b , int off , int len) 读取 len字节的数据从输入流到一个字节数组。试图读取多达 len字节,但可能读取到少于len字节。返回实际读取的字节数为整数。 第一个字节存储读入元素b[off],下一个b[off+1],等等。读取的字节数是最多等于len。k被读取的字节数,这些字节将存储在元素通过b[off+k-1]b[off],离开元素通过b[off+len-1] b[off+k]未受影响。read(byte[]b)就是相当于read(byte [] b , 0 , b.length),所以两者差不多,性质一样。
这里有个问题,read()无参方法读取一个字节,为什么返回的是一个int类型,而不是一个byte类型? 因为字节输入流可以操作任意类型的文件,比如图片音频等,这些文件底层都是以二进制形式的存储的,一个字节是8个二进制,也就是说我们实际read完后得到的是这样的东西(11111110,00001010),如果每次读取都返回byte,有可能在读到中间的时候遇到111111111(文件的底层按补码来存储的),那么这11111111是byte类型的-1,我们的程序是遇到-1就会停止不读了,后面的数据就读不到了,所以在读取的时候用int类型接收,如果11111111会在其前面补上24个0凑足4个字节,那么byte类型的-1就变成int类型的255了,这样可以保证整个数据读完,而结束标记的-1就是int类型
JDK11的空对象模式
JDK11为什么会增加nullInputStream方法的设计?即空对象模式
举个例子:
然后便可以始终可以这么调用,而不用再判断空了
FilterInputStream
FilterInputStream 源码如下
ByteArrayInputStream
ByteArrayInputStream属于内存IO的范畴,就是把内存中的数据又读取到内存中。
ByteArrayInputStream源码如下
BufferedInputStream
BufferedInputStream缓冲流,其实就是多给InputStream了一层包装,InputStream在读取数据时可以设置缓冲区大小,而BufferedInputStream就是将缓冲区大小默认设置为8192,即8MB
BufferedInputStream源码如下