从HttpURLConnection创建一个InputStream的副本,以便可以使用两次。

7
我使用这个问题中的代码,将InputStream转换为String:

如何在Java中将InputStream转换为String?

代码如下:
public static String convertStreamToString(java.io.InputStream is) {
    java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
    return s.hasNext() ? s.next() : "";
} 

我的输入流来自HttpURLConnection InputStream,当我将其转换为字符串时,输入流发生了变化,我不能再使用它。这是我得到的错误:

Premature end of file.' SOAP

当我将输入流转换为包含正确信息的字符串时,我该怎么做才能保留我的输入流?

具体来说,这是会发生变化的信息:

inCache = true (before false)
keepAliveConnections = 4 (before 5)
keepingAlive = false (before true)
poster = null (before it was PosterOutputStream object with values)

谢谢您。

Eduardo:你能否创建另一个InputStream并将其用于第二个客户端?在这个方法(convertStreamToString)中读取数据后,您可以将这些数据放回到另一个流中(例如:ByteArrayInputStream),然后将其发送给需要从输入流中读取相同数据的第二个客户端。 - mhshams
嗨,Mohammad,我想我不完全明白你的意思。你能否回答问题并提供更多详细信息?如果它正常工作,我将非常乐意给予您我的奖励。是的,你在另一个问题的评论中是正确的,我需要保持我的InputStream不变,然后才能正确地将其转换为SOAP消息。谢谢! - Eduardo
3个回答

10
如果您将输入流传入扫描程序或以其他方式读取其数据,实际上您正在消耗其数据,并且该流中将没有可用的数据。
您可能需要创建一个具有相同数据的新输入流,并使用它来替换原始输入流。例如:
ByteArrayOutputStream into = new ByteArrayOutputStream();
byte[] buf = new byte[4096];

// inputStream is your original stream. 
for (int n; 0 < (n = inputStream.read(buf));) {
    into.write(buf, 0, n);
}
into.close();

byte[] data = into.toByteArray();

//This is your data in string format.
String stringData = new String(data, "UTF-8"); // Or whatever encoding  

//This is the new stream that you can pass it to other code and use its data.    
ByteArrayInputStream newStream = new ByteArrayInputStream(data);

1
我看到你放了4096,工作得很好。但是,我该如何获得输入流的大小?我没有看到一个getsize方法?谢谢! - Eduardo
2
那个数字(4096)只是缓冲区大小。你可以选择任何你喜欢的其他数字。你不能在不读取它的情况下找到输入流大小。你可以使用InputStream.available(),但它将返回流中当前可用的字节数。实际上,在您读取流的过程中,流的大小可能会发生变化。因此,唯一有保证的解决方案是读取数据直到达到流的末尾。 - mhshams

2
扫描器会读取流直到结尾并关闭它,因此不再可用。使用PushbackInputStream将其包装为输入流,然后使用unread()方法。

嗨,安东尼,我相信你是对的。但是你提到的unread()方法该怎么使用呢?非常感谢!!! - Eduardo
1
@Antony,使用PushbackInputStream时,您无法将数据标记为未读状态。我认为Eduardo需要保持原始InputStream(来自URL连接的那个)不变。 - mhshams

0
尝试使用Apache工具。 在我的当前项目中,我做了同样的事情。

InputStream xml = connection.getInputStream();

String responseData = IOUtils.toString(xml);

你可以从Apache获取IOUtils [导入org.apache.commons.io.IOUtils]


嗨,实际上这在我发布的问题中已经有注释了,我也尝试过了。但是最终我的输入流也被消耗完了,因此无法使用。谢谢! - Eduardo
您可以随意使用字符串数据。由于流无法向后读取,如果需要此类支持,您将在后续遇到许多问题。 - RaceBase
是的,我可以随意使用字符串,但是我需要两次使用输入流。第一次用于转换为字符串(以确定应该使用的正确的SOAP版本),第二次用于将输入流转换为SOAP消息。 - Eduardo
我仍然无法理解在 SOAP 消息中使用 String 而不是 Stream 的问题。 - RaceBase
无法将字符串转换为SOAP消息,只能转换输入流。 - Eduardo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接