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()。