首先,进入javax.servlet.ServletInputStream类,该类继承了InputStream,从InputStream中调用了read方法,这里我们先看read的源码和注释
/** Reads up to len bytes of data from the input stream into an array of bytes. An *attempt is made to read as many as len bytes, but a smaller number may be read. 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.
*If len is zero, then no bytes are read and 0 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 -1 is returned; otherwise, at least one byte is read and stored into b.
*The first byte read is stored into element b[off], the next one into b[off+1], and so *on. The number of bytes read is, at most, equal to len. Let k be the number of bytes *actually read; these bytes will be stored in elements b[off] through b[off+k-1], leaving *elements b[off+k] through b[off+len-1] unaffected.
*In every case, elements b[0] through b[off] and elements b[off+len] through b[b.length-*1] are unaffected.
*The read(b, off, len) method for class InputStream simply calls the method read() *repeatedly. If the first such call results in an IOException, that exception is returned *from the call to the read(b, off, len) method. If any subsequent call to read() results *in a IOException, the exception is caught and treated as if it were end of file; the *bytes read up to that point are stored into b 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 len 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.
*Params:
*b – the buffer into which the data is read.
*off – the start offset in array b at which the data is written.
*len – the maximum number of bytes to read.
*Returns:
*the total number of bytes read into the buffer, or -1 if there is no more data because *the end of the stream has been reached.
*Throws:
*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.
*NullPointerException – If b is null.
*IndexOutOfBoundsException – If off is negative, len is negative, or len is greater than *b.length - off
*See Also:
*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();
if (c == -1) {
break;
}
b[off + i] = (byte)c;
}
} catch (IOException ee) {
}
return i;
}
从输入流读取一定数量的字节,存储到缓冲区中,如果已经到达流的末尾,没有更多的数据,则返回-1.
InputStream中还有mark方法以及reset方法,mark用法用以标记输入流中的当前位置,之后调用reset方法时,将此流重新定位到该输入流的上一次调用mark的位置,mark的一般约定是,如果方法markSupported返回true,流将以某种方式记住调用mark后读取的所有字节,并随时准备在调用reset方法时再次提供相同的字节。但是,如果在调用reset之前从流中读取了超过readlimit的字节,则流根本不需要记住任何数据。
但是在InputStream中的markSupported方法直接返回了false以及reset方法直接抛出异常,看源码:
/**
* Repositions this stream to the position at the time the
* <code>mark</code> method was last called on this input stream.
*
* <p> The general contract of <code>reset</code> is:
*
* <ul>
* <li> If the method <code>markSupported</code> returns
* <code>true</code>, then:
*
* <ul><li> If the method <code>mark</code> has not been called since
* the stream was created, or the number of bytes read from the stream
* since <code>mark</code> was last called is larger than the argument
* to <code>mark</code> at that last call, then an
* <code>IOException</code> might be thrown.
*
* <li> If such an <code>IOException</code> is not thrown, then the
* stream is reset to a state such that all the bytes read since the
* most recent call to <code>mark</code> (or since the start of the
* file, if <code>mark</code> has not been called) will be resupplied
* to subsequent callers of the <code>read</code> method, followed by
* any bytes that otherwise would have been the next input data as of
* the time of the call to <code>reset</code>. </ul>
*
* <li> If the method <code>markSupported</code> returns
* <code>false</code>, then:
*
* <ul><li> The call to <code>reset</code> may throw an
* <code>IOException</code>.
*
* <li> If an <code>IOException</code> is not thrown, then the stream
* is reset to a fixed state that depends on the particular type of the
* input stream and how it was created. The bytes that will be supplied
* to subsequent callers of the <code>read</code> method depend on the
* particular type of the input stream. </ul></ul>
*
* <p>The method <code>reset</code> for class <code>InputStream</code>
* does nothing except throw an <code>IOException</code>.
*
* @exception IOException if this stream has not been marked or if the
* mark has been invalidated.
* @see java.io.InputStream#mark(int)
* @see java.io.IOException
*/
public synchronized void reset() throws IOException {
throw new IOException("mark/reset not supported");
}
/**
* Tests if this input stream supports the <code>mark</code> and
* <code>reset</code> methods. Whether or not <code>mark</code> and
* <code>reset</code> are supported is an invariant property of a
* particular input stream instance. The <code>markSupported</code> method
* of <code>InputStream</code> returns <code>false</code>.
*
* @return <code>true</code> if this stream instance supports the mark
* and reset methods; <code>false</code> otherwise.
* @see java.io.InputStream#mark(int)
* @see java.io.InputStream#reset()
*/
public boolean markSupported() {
return false;
}
由此可见,InputStream中不让我们重复读取输入流,只能读取一次。