浅谈request.getinputstream只能读取一次的问题

网络编程 2021-07-05 11:23www.168986.cn编程入门
狼蚁网站SEO优化长沙网络推广就为大家带来一篇浅谈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 pliance with
  the License. You may obtain a copy of the License at
 
    http://.apache./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 ourred
   /
  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只能读取一次的问题就是长沙网络推广分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持狼蚁SEO。

Copyright © 2016-2025 www.168986.cn 狼蚁网络 版权所有 Power by