首先,我们复习一下inputstream read方法的基础知识,
java inputstream read方法内部有一个,postion,标志当前流读取到的位置,每读取一次,位置就会移动一次,如果读到最后,inputstream.read方法会返回-1,标志已经读取完了,如果想再次读取,可以调用inputstream.reset方法,position就会移动到上次调用mark的位置,mark默认是0,所以就能从头再读了。
当然,能否reset是有条件的,它取决于marksupported,marksupported() 方法返回是否可以mark/reset
我们再回头看request.getinputstream
request.getinputstream返回的值是servletinputstream,查看servletinputstream源码发现,没有重写reset方法,所以查看inputstream源码发现marksupported 返回false,并且reset方法,直接抛出异常。
inputstream.java
public boolean marksupported() {
return false;
}
public synchronized void reset() throws ioexception {
throw new ioexception("mark/reset not supported");
}
综上所述,在request.getinputstream读取一次后position到了文件末尾,第二次就读取不到数据,由于无法reset(),所以,request.getinputstream只能读取一次。
总结:
这个问题最根本还是对java io的read、reset方法的深入理解,尤其是read方法的内部实现原理。
附servletinputstream.java源码
/*
* licensed to the apache software foundation (asf) under one or more
* contributor license agreements. see the notice file distributed with
* this work for additional information regarding copyright ownership.
* the asf licenses this file to you under the apache license, version 2.0
* (the "license"); you may not use this file except in compliance with
* the license. you may obtain a copy of the license at
*
* http://www.apache.org/licenses/license-2.0
*
* unless required by applicable law or agreed to in writing, software
* distributed under the license is distributed on an "as is" basis,
* without warranties or conditions of any kind, either express or implied.
* see the license for the specific language governing permissions and
* limitations under the license.
*/
package javax.servlet;
import java.io.ioexception;
import java.io.inputstream;
/**
* provides an input stream for reading binary data from a client request,
* including an efficient readline
method for reading data one line
* at a time. with some protocols, such as http post and put, a
* servletinputstream
object can be used to read data sent from the
* client.
*
* a servletinputstream
object is normally retrieved via the
* {@link servletrequest#getinputstream} method.
*
* this is an abstract class that a servlet container implements. subclasses of
* this class must implement the java.io.inputstream.read()
method.
*
* @see servletrequest
*/
public abstract class servletinputstream extends inputstream {
/**
* does nothing, because this is an abstract class.
*/
protected servletinputstream() {
// noop
}
/**
* reads the input stream, one line at a time. starting at an offset, reads
* bytes into an array, until it reads a certain number of bytes or reaches
* a newline character, which it reads into the array as well.
*
* this method returns -1 if it reaches the end of the input stream before
* reading the maximum number of bytes.
*
* @param b
* an array of bytes into which data is read
* @param off
* an integer specifying the character at which this method
* begins reading
* @param len
* an integer specifying the maximum number of bytes to read
* @return an integer specifying the actual number of bytes read, or -1 if
* the end of the stream is reached
* @exception ioexception
* if an input or output exception has occurred
*/
public int readline(byte[] b, int off, int len) throws ioexception {
if (len <= 0) {
return 0;
}
int count = 0, c;
while ((c = read()) != -1) {
b[off++] = (byte) c;
count++;
if (c == '\n' || count == len) {
break;
}
}
return count > 0 ? count : -1;
}
/**
* returns true
if all the data has been read from the stream,
* else false
.
*
* @since servlet 3.1
*/
public abstract boolean isfinished();
/**
* returns true
if data can be read without blocking, else
* false
. if this method is called and returns false, the
* container will invoke {@link readlistener#ondataavailable()} when data is
* available.
*
* @since servlet 3.1
*/
public abstract boolean isready();
/**
* sets the {@link readlistener} for this {@link servletinputstream} and
* thereby switches to non-blocking io. it is only valid to switch to
* non-blocking io within async processing or http upgrade processing.
*
* @param listener the non-blocking io read listener
*
* @throws illegalstateexception if this method is called if neither
* async nor http upgrade is in progress or
* if the {@link readlistener} has already
* been set
* @throws nullpointerexception if listener is null
*
* @since servlet 3.1
*/
public abstract void setreadlistener(readlistener listener);
}
以上这篇浅谈request.getinputstream只能读取一次的问题就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持萬仟网。
希望与广大网友互动??
点此进行留言吧!