我正在处理一些Java代码,其中有一个我读过一次的InputStream,然后我需要在同一个方法中再次读取它。
问题是我需要将它的位置重置为开头才能读取它两次。
我找到了解决问题的黑客解决方案:
is.mark(Integer.MAX_VALUE);
//Read the InputStream is fully
// { ... }
try
{
is.reset();
}
catch (IOException e)
{
e.printStackTrace();
}
这个解决方案会导致一些未经预料到的行为吗?或者它会愚蠢吗?
如上所述,您无法保证,因为 mark()
不要求报告是否成功。要获得保证,您必须先致电 的markSupported(),它必须返回 true
。
同样如上所述,指定的读取限制非常危险。如果您碰巧使用缓冲内存的流,则可能会分配2GB缓冲区。另一方面,如果您碰巧使用了 FileInputStream
, 你没事。
更好的方法是使用a BufferedInputStream
使用显式缓冲区。
你不能可靠地做到这一点;一些 InputStream
s(例如连接到终端或插座的那些)不支持 mark
和 reset
(看到 markSupported
)。如果你真的必须遍历数据两次,你需要将它读入你自己的缓冲区。
它取决于InputStream实现。您还可以考虑使用byte []是否会更好。最简单的方法是使用Apache 公地IO:
byte[] bytes = IOUtils.toByteArray(inputSream);
而不是试图重置 InputStream
将它加载到缓冲区中 StringBuilder
或者如果它是二进制数据流a ByteArrayOutputStream
。然后,您可以根据需要多次处理方法中的缓冲区。
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int read = 0;
byte[] buff = new byte[1024];
while ((read = inStream.read(buff)) != -1) {
bos.write(buff, 0, read);
}
byte[] streamData = bos.toByteArray();
对我来说,最简单的解决方案是传递可以从中获取InputStream的对象,然后再次获取它。就我而言,它来自一个 ContentResolver
。