A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

今天开始学习字节流。本文简单介绍所有字节输入流的父类InputStream。

InputStream是抽象类。这个抽象类是所有表示字节输入流的类的父类。继承这个抽象类的类必须提供返回下一个输入字节的方法。定义如下:

public abstract class InputStream implements Closeable
方法
方法
说明

public abstract int read() throws IOException;
从输入流中读取数据的下个字节。

public int read(byte b[]) throws IOException{…}
从输入流中读取一定数量的字节,并将其存储在缓冲区数组b中。

public int read(byte b[], int off, int len) throws IOException{…}
将输入流中最多len个数据字节读入byte数组。

public long skip(long n) throws IOException{…}
跳过和丢弃此输入流中数据的n个字节。

public int available() throws IOException{…}
返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数。

public void close() throws IOException {}
关闭此输入流并释放与该流关联的所有系统资源。

public synchronized void mark(int readlimit) {}
在此输入流中标记当前的位置。对reset方法的后续调用会在最后标记的位置重新定位此流,以便后续读取重新读取相同的字节。

public synchronized void reset() throws IOException {…}
将此流重新定位到最后一次对此输入流调用mark方法时的位置。

public boolean markSupported() {…}
测试此输入流是否支持mark和reset方法。
read()/** * 从输入流中读取数据的下个字节。读取的字节为int型,范围为0~255。 * 如果因为到了流末尾导致没有可用的字节,返回-1。 * 在输入数据可用、检测到流末尾或者抛出异常前,此方法一直阻塞。 * * 子类必须提供方法的实现。 * * @return     如果到达流末尾,返回-1,否则返回从输入流中读取到的数据的下个字节 * @exception  IOException  如果发生I/O错误 */public abstract int read() throws IOException;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
read(byte b[])/** * 从输入流中读取一定数量的字节并把它们保存到缓冲数组b中。返回读取的字节数。在输入数据可用、检测到文件末尾或者抛出异常前,此方法一直阻塞。 * * 如果b的长度为0,不会读取字节,并返回0;否则至少会尝试读取一个字节。如果因为流在文件末尾导致没有字节可用,返回-1;否则至少读取一个字节并保存到b中。 * * 将读取的第一个字节存储在b[0]中,下一个字节存储在b[1]中,依次类推。读取的字节数最多等于b的长度。设k为实际读取的字节数;这些字节将存储在 b[0]到b[k-1]的元素中,不影响b[k]到b[b.length-1]的元素。 * * 类InputStream的read(b)方法的相当于:read(b, 0, b.length)  * * @param      b   存储读入数据的缓冲区。 * @return     读入缓冲区的总字节数;如果因为已经到达流末尾而不再有数据可用,则返回-1。 * @exception  IOException  如果不是因为流位于文件末尾而无法读取第一个字节;如果输入流已关闭;如果发生其他I/O错误。 * @exception  NullPointerException  如果b为null * @see        java.io.InputStream#read(byte[], int, int) */public int read(byte b[]) throws IOException {    return read(b, 0, b.length);}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
read(byte b[], int off, int len)/** * 将输入流中最多len个字节读入byte数组。尝试读取len个字节,但读取的字节也可能小于该值。以整数形式返回实际读取的字节数。 *  * 在输入数据可用、检测到流末尾或者抛出异常前,此方法一直阻塞。 *  * 如果len为0,则不读取任何字节并返回0;否则,尝试读取至少一个字节。如果因为流位于文件末尾而没有可用的字节,则返回值-1;否则,至少读取一个字节并将其存储在b中。 * * 将读取的第一个字节存储在元素b[off]中,下一个存储在 b[off+1] 中,依次类推。读取的字节数最多等于len。设k为实际读取的字节数;这些字节将存储在b[off]到b[off+k-1]的元素中,不影响b[off+k]到b[off+len-1]的元素。 *  * 在任何情况下,b[0]到b[off]的元素以及b[off+len]到b[b.length-1] 的元素都不会受到影响。 *  * 类InputStream的read(b, off, len)方法重复调用方法read()。如果第一次这样的调用导致IOException,则从对read(b, off, len)方法的调用中返回该异常。如果对read()的任何后续调用导致IOException,则捕获该异常并将其视为到达文件末尾;到达该点时读取的字节存储在b中,并返回发生异常之前读取的字节数。在已读取输入数据len的请求数量、检测到文件结束标记、抛出异常前,此方法的默认实现将一直阻塞。建议子类提供此方法更为有效的实现。 *  * @param      b     读入数据的缓冲区。 * @param      off   数组 b 中将写入数据的初始偏移量。 * @param      len   要读取的最大字节数。 * @return     读入缓冲区的总字节数;如果因为已到达流末尾而不再有数据可用,则返回-1。 * @exception  IOException 如果不是因为位于文件末尾而无法读取第一个字节;如果输入流已关闭;如果发生其他 I/O 错误。 * @exception  NullPointerException  如果 b 为 null。 * @exception  IndexOutOfBoundsException 如果off为负,len为负,或者len大于b.length - off * @see        java.io.InputStream#read() */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();    // 如果因为流位于文件末尾而没有可用的字节,返回-1    if (c == -1) {        return -1;    }    // 将读取的第一个字节存储在元素b[off]中    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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
skip(long n)/** * 跳过和丢弃此输入流中数据的n个字节。出于各种原因,skip方法结束时跳过的字节数可能小于该数,也可能为0。导致这种情况的原因很多,跳过n个字节之前已到达文件末尾只是其中一种可能。返回跳过的实际字节数。如果n为负,方法返回0,,不跳过任何字节。子类可能对负值有不一样的处理。 * * skip方法创建一个byte数组,然后重复将字节读入其中,直到读够n个字节或已到达流末尾为止。建议子类提供此方法更为有效的实现。例如,可依赖搜索能力的实现。 * * @param      n   要跳过的字节数。 * @return     实际跳过的字节数 * @exception  IOException  如果流不支持搜索,或者发生其他 I/O 错误。 */public long skip(long n) throws IOException {    long remaining = n;    int nr;    // 如果n<=0,返回0    if (n <= 0) {        return 0;    }    int size = (int)Math.min(MAX_SKIP_BUFFER_SIZE, remaining);    // 创建一个byte数组,然后重复将字节读入其中,直到读够n个字节或已到达流末尾为止。    byte[] skipBuffer = new byte[size];    while (remaining > 0) {        nr = read(skipBuffer, 0, (int)Math.min(size, remaining));        if (nr < 0) {            break;        }        remaining -= nr;    }    return n - remaining;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
available()/** * 返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数。下一个调用可能是同一个线程,也可能是另一个线程。一次读取或跳过此估计数个字节不会受阻塞,但读取或跳过的字节数可能小于该数。 * * 注意,有些InputStream的实现将返回流中的字节总数,但也有很多实现不会这样做。试图使用此方法的返回值分配缓冲区,以保存此流所有数据的做法是不正确的。 * * 如果已经调用close()方法关闭了此输入流,那么此方法的子类实现可以选择抛出IOException。 * * InputStream的available方法总是返回0。 * * 此方法应该由子类重写。 * * @return     可以不受阻塞地从此输入流读取(或跳过)的估计字节数;如果到达输入流末尾,则返回0。 * @exception  IOException 如果发生 I/O 错误。 */public int available() throws IOException {    //InputStream的available方法总是返回0。    return 0;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
close()/** * 关闭此输入流并释放与该流关联的所有系统资源。 * InputStream 的close方法不执行任何操作。 * * @exception  IOException  如果发生I/O错误。 */public void close() throws IOException {}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
mark(int readlimit)/** * 在此输入流中标记当前的位置。对reset方法的后续调用会在最后标记的位置重新定位此流,以便后续读取重新读取相同的字节。 * * readlimit告知此输入流在标记位置失效之前允许读取的字节数。 * * mark的一般约定是:如果方法markSupported返回true,那么输入流总是在调用mark之后记录所有读取的字节,并时刻准备在调用方法reset时(无论何时),再次提供这些相同的字节。但是,如果在调用reset之前可以从流中读取多于readlimit的字节,则不需要该流记录任何数据。 * * 标记已关闭的流对其无效 * * InputStream的mark方法不执行任何操作。 * * @param   readlimit   在标记位置失效前可以读取字节的最大限制。 * @see     java.io.InputStream#reset() */public synchronized void mark(int readlimit) {}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
reset()/** * 将此流重新定位到最后一次对此输入流调用mark方法时的位置。 * * reset 的一般约定是: * * 1.如果方法 markSupported 返回 true,那么: * 1.1如果创建流以后未调用方法mark,或最后调用mark以后从该流读取的字节数大于最后调用mark时的参数,则可能抛出IOException。 * 1.2如果未抛出这样的IOException,则将该流重新设置为这种状态:最近一次调用mark以后(如果未调用过mark,则从文件开头开始)读取的所有字节将重新提供给read方法的后续调用者,后跟任何从调用reset时起将作为下一输入数据的字节。 * * 2.如果方法markSupported返回false,那么: * 2.1对reset 的调用可能抛出IOException。 * 2.2如果未抛出IOException,则将该流重新设置为一种固定状态,该状态取决于输入流的特定类型及其创建方式。提供给read方法后续调用者的字节取决于特定类型的输入流。 * * 除了抛出 IOException 之外,类 InputStream 的方法 reset 不执行任何操作。 * * @exception  IOException  i如果未标记此流或该标记失效。 * @see     java.io.InputStream#mark(int) * @see     java.io.IOException */public synchronized void reset() throws IOException {    throw new IOException("mark/reset not supported");}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
markSupported()/** * 测试此输入流是否支持mark和reset方法。是否支持mark和reset是特定输入流实例的不变属性。 InputStream 的markSupported方法返回false。 * * @return  如果此输入流实例支持mark和reset方法,则返回true;否则返回false。 * @see     java.io.InputStream#mark(int) * @see     java.io.InputStream#reset() */public boolean markSupported() {    return false;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
总结
  • 字节输入流必须提供返回下一个输入字节的read()方法。因为所有字节输入流的父类InputStream有这样一个抽象方法:public abstract int read()。

对InputStream的介绍就到这里。想了解更多内容请参考

版权声明


1 个回复

倒序浏览

很不错,受教了
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马