浅谈request.getinputstream只能读取一次的问题
首先,我们复习一下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 <code>readline</code> method for reading data one line * at a time. with some protocols, such as http post and put, a * <code>servletinputstream</code> object can be used to read data sent from the * client. * <p> * a <code>servletinputstream</code> object is normally retrieved via the * {@link servletrequest#getinputstream} method. * <p> * this is an abstract class that a servlet container implements. subclasses of * this class must implement the <code>java.io.inputstream.read()</code> 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. * <p> * 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 <code>true</code> if all the data has been read from the stream, * else <code>false</code>. * * @since servlet 3.1 */ public abstract boolean isfinished(); /** * returns <code>true</code> if data can be read without blocking, else * <code>false</code>. 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只能读取一次的问题就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。
下一篇: 家常做法的红烧鸡怎么做才好吃
推荐阅读
-
浅谈request.getinputstream只能读取一次的问题
-
STM32 SWD 只能下载一次的问题
-
记录一次拦截器post请求参数读取一次的问题
-
用ADO更新MYSQL报“无法为更新定位行。一些值可能已在最后一次读取后已更改”问题的解决_MySQL
-
用ADO更新MYSQL报“无法为更新定位行。一些值可能已在最后一次读取后已更改”问题的解决_MySQL
-
request.getInputStream()只能获取一次的问题
-
STM32 SWD 只能下载一次的问题
-
type=file的change事件只能执行一次的问题及解决方法实例
-
request.inputStream()和response.outputStream()只能读一次的问题
-
springboot请求体中的流只能读取一次的问题