InputStream是一个抽象类,实现了Closeable接口。InputStream是代表字节输入流的所有类的父类。程序想要定义一个InputStream抽象类的子类,则必须提供(实现)一个返回输入的下一个字节的方法。

来看看InputStream内部结构:

下面一个一个地来看这些方法。

1、close()方法:关闭字节流并释放字节流相关的系统资源

close方法其实是实现Closeable接口的方法。并且InputStream的close方法是一个空实现。这意味着继承InputStream的子类虽然不是强制性要重写close方法,但还是建议根据业务进行重写。

/*** Closes this input stream and releases any system resources associated* with the stream.** <p> The <code>close</code> method of <code>InputStream</code> does* nothing.** @exception  IOException  if an I/O error occurs.*/
public void close() throws IOException {}

2、read()方法:读取下一个字节,并返回该字节的ascii码(字节值的十进制表示方式,即ascii码)

read()方法从输入流中读取下一个字节的数据。返回的字节值是一个1~255区间的int类型值(字节值的十进制整形表示)。如果达到了输入流的末尾没有剩余的字节了。将返回-1。

该方法将阻塞线程,直到出现以下情况

1、输入数据可用;

2、检测到流的结尾;

3、抛出一个异常

注意:read()方法是一个抽象方法,即子类必须实现这个方法。

/*** Reads the next byte of data from the input stream. The value byte is* returned as an <code>int</code> in the range <code>0</code> to* <code>255</code>. If no byte is available because the end of the stream* has been reached, the value <code>-1</code> is returned. This method* blocks until input data is available, the end of the stream is detected,* or an exception is thrown.** <p> A subclass must provide an implementation of this method.** @return     the next byte of data, or <code>-1</code> if the end of the*             stream is reached.* @exception  IOException  if an I/O error occurs.*/
public abstract int read() throws IOException;

3、read(byte b[]):读取一些字节并存入字节数组中,返回实际读取字节串长度

从输入流中读取一些字节,并存储这些字节到缓冲数组b中。实际读取的字节数量以整数的形式返回(即read(byte b[])返回值是实际读取到的字节数量。这也是一个阻塞方法,同read()。

如果字节数组b的长度为空,则读取不到字节并返回0。否则,将尝试读取至少一个字节。如果由于输入流到达了文件末尾导致没有剩余的字节,将返回-1;否则,至少读取一个字节并存储进数组数组b。

读取到的第一个字节被存到b[0]位置,下一个字节存入到b[1],以此类推。读取到的这些字节的数量最多等于数组b的长度。设k为实际读取的字节数量,这些字节将被存储到b[0]到b[k-1],而b[k]到b[b.length-1]之间的元素不会被影响。

read(b)方法和read(b, 0, b.length)作用是一样的。

可以看到,read(byte b[]) 实际上是调用read(byte b[], int off, int len)。

/*** Reads some number of bytes from the input stream and stores them into* the buffer array <code>b</code>. The number of bytes actually read is* returned as an integer.  This method blocks until input data is* available, end of file is detected, or an exception is thrown.** <p> If the length of <code>b</code> is zero, then no bytes are read and* <code>0</code> is returned; otherwise, there is an attempt to read at* least one byte. If no byte is available because the stream is at the* end of the file, the value <code>-1</code> is returned; otherwise, at* least one byte is read and stored into <code>b</code>.** <p> The first byte read is stored into element <code>b[0]</code>, the* next one into <code>b[1]</code>, and so on. The number of bytes read is,* at most, equal to the length of <code>b</code>. Let <i>k</i> be the* number of bytes actually read; these bytes will be stored in elements* <code>b[0]</code> through <code>b[</code><i>k</i><code>-1]</code>,* leaving elements <code>b[</code><i>k</i><code>]</code> through* <code>b[b.length-1]</code> unaffected.** <p> The <code>read(b)</code> method for class <code>InputStream</code>* has the same effect as: <pre><code> read(b, 0, b.length) </code></pre>** @param      b   the buffer into which the data is read.* @return     the total number of bytes read into the buffer, or*             <code>-1</code> if there is no more data because the end of*             the stream has been reached.* @exception  IOException  If the first byte cannot be read for any reason* other than the end of the file, if the input stream has been closed, or* if some other I/O error occurs.* @exception  NullPointerException  if <code>b</code> is <code>null</code>.* @see        java.io.InputStream#read(byte[], int, int)*/
public int read(byte b[]) throws IOException {return read(b, 0, b.length);
}

4、read(byte b[], int off, int len) 读取一些字节,并存储到字节数组的指定位置,返回实际读取字节串长度

从输入流中读取最多len个字节数据进字节数组中。该方法尝试读取尽可能和len一样多的字节,但是可能读取到更小数量的字节。该方法返回一个整形数,代表实际读取到的字节数量。

其实可以直接看代码就能明白其是如何实现的。这个方法时InputStream抽象类的一个核心方法,读取的大部分逻辑都在这里,方法实现比较简单,但是其思想值得借鉴。

该方法体内部实际还是调用read()抽象方法来进行读取字节(在for循环中一个一个地读取字节)。这种思想很好地降低了代码耦合,它不需要关心是如何实现read()方法的。 在read()方法的基础上增加一系列逻辑就能读取字节数组了。抽象read()方法的具体实现交给子类去完成,抽象类把处理逻辑搭建好,这种思想在很多地方都用得到:比如android中的baseActivity就是在base基类中把逻辑流程都实现好,具体用到的某个方法在子类中实现。这样可以降低代码耦合,并大大地减少了重复代码。

/*** Reads up to <code>len</code> bytes of data from the input stream into* an array of bytes.  An attempt is made to read as many as* <code>len</code> bytes, but a smaller number may be read.* The number of bytes actually read is returned as an integer.** <p> This method blocks until input data is available, end of file is* detected, or an exception is thrown.** <p> If <code>len</code> is zero, then no bytes are read and* <code>0</code> is returned; otherwise, there is an attempt to read at* least one byte. If no byte is available because the stream is at end of* file, the value <code>-1</code> is returned; otherwise, at least one* byte is read and stored into <code>b</code>.** <p> The first byte read is stored into element <code>b[off]</code>, the* next one into <code>b[off+1]</code>, and so on. The number of bytes read* is, at most, equal to <code>len</code>. Let <i>k</i> be the number of* bytes actually read; these bytes will be stored in elements* <code>b[off]</code> through <code>b[off+</code><i>k</i><code>-1]</code>,* leaving elements <code>b[off+</code><i>k</i><code>]</code> through* <code>b[off+len-1]</code> unaffected.** <p> In every case, elements <code>b[0]</code> through* <code>b[off]</code> and elements <code>b[off+len]</code> through* <code>b[b.length-1]</code> are unaffected.** <p> The <code>read(b,</code> <code>off,</code> <code>len)</code> method* for class <code>InputStream</code> simply calls the method* <code>read()</code> repeatedly. If the first such call results in an* <code>IOException</code>, that exception is returned from the call to* the <code>read(b,</code> <code>off,</code> <code>len)</code> method.  If* any subsequent call to <code>read()</code> results in a* <code>IOException</code>, the exception is caught and treated as if it* were end of file; the bytes read up to that point are stored into* <code>b</code> and the number of bytes read before the exception* occurred is returned. The default implementation of this method blocks* until the requested amount of input data <code>len</code> has been read,* end of file is detected, or an exception is thrown. Subclasses are encouraged* to provide a more efficient implementation of this method.** @param      b     the buffer into which the data is read.* @param      off   the start offset in array <code>b</code>*                   at which the data is written.* @param      len   the maximum number of bytes to read.* @return     the total number of bytes read into the buffer, or*             <code>-1</code> if there is no more data because the end of*             the stream has been reached.* @exception  IOException If the first byte cannot be read for any reason* other than end of file, or if the input stream has been closed, or if* some other I/O error occurs.* @exception  NullPointerException If <code>b</code> is <code>null</code>.* @exception  IndexOutOfBoundsException If <code>off</code> is negative,* <code>len</code> is negative, or <code>len</code> is greater than* <code>b.length - off</code>* @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();if (c == -1) {return -1;}b[off] = (byte)c;int i = 1;try {for (; i < len ; i++) {c = read(); //返回的是字节值的十进制表示方式,即ascii码值if (c == -1) {break;}b[off + i] = (byte)c; //c是字节值的十进制表示方法,这里需要转换成字节类型}} catch (IOException ee) {}return i;
}

5、skip(long n)方法:跳过并丢弃输入流中的n个字节数据,并返回实际跳过的字节数量

该方法跳过并丢弃输入流中的n个字节数据。由于一些原因,skip方法可能会跳过一些更小数量的字节,可能是0。这可能由多种情况中的任何一种造成;在跳过n个字节之前到达文件末尾是唯一的可能性。

返回的是实际跳过的字节数量值。如果n是负数,则该方法返回0,并且没有字节被跳过。子类可能以不同方式处理负值。

类中的skip方法创建一个字节数组,并在之后重复地读取字节进入数组中,直到读取了n个字节,或到达了输入流的末尾。鼓励子类提供一个更高效的实现。比如,该实现可能依赖于seek的能力。

/*** Skips over and discards <code>n</code> bytes of data from this input* stream. The <code>skip</code> method may, for a variety of reasons, end* up skipping over some smaller number of bytes, possibly <code>0</code>.* This may result from any of a number of conditions; reaching end of file* before <code>n</code> bytes have been skipped is only one possibility.* The actual number of bytes skipped is returned. If {@code n} is* negative, the {@code skip} method for class {@code InputStream} always* returns 0, and no bytes are skipped. Subclasses may handle the negative* value differently.** <p> The <code>skip</code> method of this class creates a* byte array and then repeatedly reads into it until <code>n</code> bytes* have been read or the end of the stream has been reached. Subclasses are* encouraged to provide a more efficient implementation of this method.* For instance, the implementation may depend on the ability to seek.** @param      n   the number of bytes to be skipped.* @return     the actual number of bytes skipped.* @exception  IOException  if the stream does not support seek,*                          or if some other I/O error occurs.*/
public long skip(long n) throws IOException {long remaining = n;int nr;if (n <= 0) {return 0;}int size = (int)Math.min(MAX_SKIP_BUFFER_SIZE, remaining);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;
}

skip内部具体实现是值得研究一下的。假如输入流中的字节数量大于skip方法的参数n,则可以成功跳过n个字节;相反情况则在循环中nr = read(skipBuffer, 0, (int)Math.min(size, remaining));读取到输入流末尾时将返回-1,此时if判断内部会跳出循环。remaining代表还剩多少个字节没有被跳过,所以返回值为n - remaining。这种情况下,实际返回skip数量值就小于参数n。

6、available()方法:返回输入流中可读或可跳过的字节数量估计值

在不会被输入流的下一次方法调用阻塞情况下,返回可从此输入流读取(或跳过)的字节数的估计值。下次调用可能是在相同线程或其他线程。一次简单的读取或跳过许多字节将不会被阻塞,但可能读取或跳过更少的字节。

注意,尽管一些InputStream的实现类将返回输入流中字节数量的总值,但大部分InputStream的实现类却不会这么做。使用此方法的返回值来分配用于保存此流中所有数据的缓冲区永远都是错误的。

如果已经调用过close方法关闭了输入流,则该方法的子类实现可能选择抛出一个IOException(即假如一个输入流已经被close了,再调用该输入流的available()方法将抛出异常)。

最后,这个方法应该被子类重写。

/*** Returns an estimate of the number of bytes that can be read (or* skipped over) from this input stream without blocking by the next* invocation of a method for this input stream. The next invocation* might be the same thread or another thread.  A single read or skip of this* many bytes will not block, but may read or skip fewer bytes.** <p> Note that while some implementations of {@code InputStream} will return* the total number of bytes in the stream, many will not.  It is* never correct to use the return value of this method to allocate* a buffer intended to hold all data in this stream.** <p> A subclass' implementation of this method may choose to throw an* {@link IOException} if this input stream has been closed by* invoking the {@link #close()} method.** <p> The {@code available} method for class {@code InputStream} always* returns {@code 0}.** <p> This method should be overridden by subclasses.** @return     an estimate of the number of bytes that can be read (or skipped*             over) from this input stream without blocking or {@code 0} when*             it reaches the end of the input stream.* @exception  IOException if an I/O error occurs.*/
public int available() throws IOException {return 0;
}

7、剩余方法

mark(int readlimit)、reset()和markSupported()。

InputStream输入字节流相关推荐

  1. IO流:输入字节流:InputStream 、 输出字节流:OutputStream 、输入字符流:Reader 、输出字符流:Writer、 BufferedInputStream

    ## 1_ IO流的介绍及其分类          * IO流:          *         I: Input 输入          *         O: Output 输出      ...

  2. java fileinputstream转换字节流_FileInputStream输入字节流

    packagecom.javaSe.FileInputStream;importjava.io.FileInputStream;importjava.io.FileNotFoundException; ...

  3. Java学习总结:42(字节流和字符流)

    字节流与字符流 上一节我们学习了文件操作类File,但是File类虽然可以操作文件,但是却不能操作文件的内容.如果要进行文件内容的操作,就必须依靠流的概念来完成.流在实际中分为输入流和输出流两种,输入 ...

  4. java对文件内容操作 -- 输入输出流

    目录 InputStream(输入字节流)和OutputStream(输出字节流) Reader(字符输入流)与Writer(字符输出流) Print 流 我们通过对File类的学习, 了解到File ...

  5. InputStream类、OutputStream类、BufferedInputStream类与BufferedOutputStream类--Java基础084

    package com.sqf.io;import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundE ...

  6. Java Stream(流)的分类, 四大基本流的介绍

    上一篇文章已经介绍过什么是流, 以及流的基本概念 http://blog.csdn.net/nvd11/article/details/29917065 本文主要介绍java四大基本流的方法. 一, ...

  7. java上机题四取三排列_Java练习题

    Java的问答题. 一. 基本 1.一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制? 可以,限制:一个文件中只能有一个public类,并且此public类必 ...

  8. socket网络编程 java_Java Web 基础(一) 基于TCP的Socket网络编程

    一.Socket简单介绍 Socket通信作为Java网络通讯的基础内容,集中了异常.I/O流模式等众多知识点.学习Socket通信,既能够了解真正的网络通讯原理,也能够增强对I/O流模式的理解. 1 ...

  9. 面试题大全1-javaSE部分-JavaEE框架中间件

    文章目录 Java面试题大全 一.JavaSE 部分 基础部分 1.Java中基本数据类型有哪些? 2.Integer 和 int的区别 3.String和StringBuilder和StringBu ...

最新文章

  1. python 整数 拆分 分段
  2. spring bean中scope=prototype“的作用
  3. Mongodb的锁 原子性 隔离性 一致性
  4. Memcache分布式部署方案
  5. rsyslod服务配置
  6. macos下npm install 报错: fsevents .... permission denined
  7. 单证票据识别之关键信息提取
  8. 推荐:免费万能视音频转换软件--格式工厂
  9. LinkButton回发报错__doPostBack('……','') 缺少对象
  10. 国科大学习资料--矩阵分析与应用(李保滨)--2015年期末考试试卷
  11. udhcpc 的使用
  12. 18个好用APP,你手机里有哪些堪称神器的APP
  13. 青蛙跳台阶问题(超详解)
  14. VS2010添加WP模板
  15. Mantis -- linux
  16. 机器视觉光源概述(选型参考)
  17. 脸部日常护理私家秘方
  18. 千年一遇的对称日20200202
  19. python 智能造句,用生成器从给定单词造句
  20. delphi 对金额double类型向上取整,保留小数位

热门文章

  1. Sniper模拟器的安装
  2. 大唐杯5G练习题(二)
  3. 常见的面试问题————NLP篇(持续更新)
  4. NSString NSArray NSDictionary NSSet 中的部分方法
  5. 说说如何在项目中引入 jBPM4 工作流框架以及遇到的坑儿
  6. fedora mysql 开机启动服务_linux -- 启动时启动服务或者执行命令
  7. android布局靠底部,android – 使用layout_gravity =“bottom”放置在LinearLayout的底部
  8. MapReduce关系代数运算——差
  9. NXP S32K1 FlexTimer模块
  10. lect01_codes02_numpy