java IO(二):FileInputStream

内容来自https://blog.csdn.net/ai_bao_zi/article/details/81097898,仅供我个人学习记录使用。

本文主要说说public int read(int r)throws IOException{}和public int read(byte[] r) throws IOException{}这两个方法。

public int read(int r)throws IOException{}
这个方法从 InputStream 对象读取指定字节的数据。返回为整数值。返回下一字节数据,如果已经到结尾则返回-1。

public int read(byte[] r) throws IOException{}
这个方法从输入流读取r.length长度的字节。返回读取的字节数。如果是文件结尾则返回-1。

对于上面这个方法,疑问是明明读取的是字节数据,为何返回值是int类型,而对于下面这个方法,问题就比较复杂:一是如果文件的内容是12345.那么流中一共有5个字节,但是我们设定的字节数组长度为2.那么会读取几次?每次情况是怎么样的?二是如果流中一共有5个字节,但是我们设定的字节数组长度为10,那么读取几次?每次情况是怎么样的?

先说上面第一个方法的问题:

  1、方法解释中的-1相当于是数据字典告诉调用者文件已到底,可以结束读取了,这里的-1是Int型

  2、那么当文件未到底时,我们读取的是字节,若返回byte类型,那么势必造成同一方法返回类型不同的情况这是不允许的

  3、我们读取的字节实际是由8位二进制组成,二进制文件不利于直观查看,可以转成常用的十进制进行展示,因此需要把读取的字节从二进制转成十进制整数,故返回int型

  4、 因此结合以上3点,保证返回类型一致以及直观查看的情况,因此该方法虽然读取的是字节但返回int型
接着是第二个方法的两个问题,这个就要从read(byte[] r)这个方法的源码来解释了:

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

可以看到调用了read(b,0,b.length)这个方法,再跳转,就是:

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

可以看到其原理是先依次判断数组b是否为null,off,len是否合法(读取的字节数必须小于等于该字符数组的指定使用长度[off为该数组开始可用的下标,一般为0,代表整个数组都可用作read]),判断过后,开始读取字符,如果流中已没有可以读取的字符,那么会返回-1,于是该方法也会返回-1,否则便把读取到的字节放入b[off],然后依次往下读放,直到读到指定数量或流中没有字符可读,注意如果此时流中没有字符可读,也是返回i(读取到的字符数量),而不会返回-1,只有下一次再调用该方法时才会返回-1。

所以对于上面那个问题的第一种情况,会先读取12,34,54(4还留着没有被变动),最后再执行一次read返回-1。对于第二种情况,由于读完5,下一次循环就会出现c==-1的情况,会直接返回i(5),然后下一次再进入该方法返回-1,所以数组中多余的5个位置会被浪费,只有前五个位置有数据(后五个位置都为0)。

这里再放上转载源的两张图,便于理解:

第一种情况

第二种情况

原文地址:https://www.cnblogs.com/MYoda/p/11163821.html