标签:throws turn return 设定 使用 ++ details 一次循环 跳转
内容来自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)。
这里再放上转载源的两张图,便于理解:
第一种情况
第二种情况
标签:throws turn return 设定 使用 ++ details 一次循环 跳转
原文地址:https://www.cnblogs.com/MYoda/p/11163821.html