JAVA使用IOUtils.toString和HttpEntity.getContent()将InputStream转换



我有一个奇怪的senario我有HTTP响应,我试图将其转换为字符串,问题是第一次它工作,但第二次InputStream数据为空
,并且我只有response1 中的数据

InputStream  is = entity.getContent();  
String response1 = IOUtils.toString(is, "utf-8");  // Here every thing is fine 
String respons2 = IOUtils.toString(is, "utf-8");   // Here the response2 is empty 
and is (InputStream) holding no data  

这里出了什么问题?我需要能够将数据保存在InputStream中,以便将来在代码中使用

然而,当检查javadoc httpEntity.getContent时,您的需求不是很清楚,我看到以下内容:

返回实体的内容流。可重复实体是期望为每次调用创建InputStream的新实例并且因此可以被多次消耗。实体不可重复的预期返回相同的InputStream实例,因此可能不会被消耗一次以上。

是否通过调用检查httpEntity是否可重复

httpEntity.isRepeatable()

如果为true,您可以执行以下操作:

InputStream  is = entity.getContent();  
String response1 = IOUtils.toString(is, "utf-8");
// retrieve a new instance of inputStream
is = entity.getContent();
String response2 = IOUtils.toString(is, "utf-8");    

最后但并非最不重要的是(因为我不知道你的确切需求(,如果实体能够不止一次地生成其数据,那么前面的代码将有所帮助,但无论如何,你应该评估以下两者之间的成本:

  • 一次性使用数据并将其保存在字符串中
  • 多次消耗数据

不,流不应该被多次读取。

如果你想保留流的内容以供重复使用,你可以这样做。在您的情况下,只需重复使用response1字符串。

在阅读之前,您应该检查流是否支持重置。您可以检查InputStream#markSupported()的结果,告诉您是否可以使用这对方法mark()/reset()

如果支持标记,则您可以在阅读时执行mark(),然后执行reset()返回开始。

如果httpEntity不可重复,则可以将InputStream封装在BufferedInputStream中;这样,您可以重置它以允许重新读取。本质上,BufferedInputStream第一次将数据读取到内部缓冲区中,然后在重新读取时重新使用缓冲区。

final int bufferSize = 1_000_000; // about 1 MB; must be large enough to hold all the http content
InputStream  is = new BufferedInputStream(entity.getContent(), bufferSize);
is.mark(bufferSize);
String response1 = IOUtils.toString(is, "utf-8");
is.reset();
String respons2 = IOUtils.toString(is, "utf-8");  

最新更新