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

本文详细探讨了ServletInputStream的使用限制,尤其是为何只能读取一次的问题。通过对InputStream的read和reset方法的分析,指出当读取到文件末尾时,由于ServletInputStream未实现reset方法,导致无法重新读取。此外,文章强调了对Java IO深入理解的重要性,特别是对read方法内部实现原理的掌握。
摘要由CSDN通过智能技术生成

首先,我们复习一下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只能读取一次的问题就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持萬仟网。

希望与广大网友互动??

点此进行留言吧!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中,request.getInputStream()方法可以用来读取HTTP请求中的请求体内容。如果请求体中是一个文件,可以通过该方法获取文件的二进制数据并进行处理。下面是一个示例代码片段,可以从HTTP请求中读取文件内容并将其保存到本地磁盘上: ```java import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class FileUploadServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { InputStream inputStream = request.getInputStream(); String saveFilePath = "/path/to/save/uploaded/file"; OutputStream outputStream = new FileOutputStream(saveFilePath); int bytesRead = -1; byte[] buffer = new byte[4096]; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); } outputStream.close(); inputStream.close(); System.out.println("文件已成功上传!"); } } ``` 在这个示例中,我们在Servlet中实现了doPost()方法,用于处理POST请求。该方法调用request.getInputStream()方法来获取HTTP请求的输入流,然后使用Java IO类将其写入本地文件中。可以通过修改saveFilePath变量来指定保存文件的路径。最后,我们关闭输入流和输出流,并打印一条消息,指示文件已成功上传。 需要注意的是,在处理文件上传时,还需要在HTTP请求头中设置Content-Type属性为multipart/form-data,以便服务器能够正确地解析请求体。否则,请求体内容可能会被服务器解析为普通的文本数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值