HttpURLConnection 两次读取 InputStream。

4
我通过HttpURLConnection向服务器发起http get请求并需要两次读取响应(InputStream):一次用于记录日志,一次用于解析响应。返回的InputStreamorg.apache.harmony.luni.internal.net.www.protocol.http.ChunkedInputStream的实例,该实例不支持标记(is.markSupported()返回false)。
因此,我无法使用mark()reset()流,而在将响应写入日志后,我也无法解析它。当然,我可以将响应读取一次到String或其他内容中,将其记录下来,然后稍后进行解析。但是,当我使用流时,我避免了潜在的OutOfMemomryError,因为流处理缓冲而不是我自己。
在这种情况下,最好的解决方案是什么,既能保留使用流的好处,又能帮助达到期望的结果:同时记录日志和解析响应?
编辑:将响应写入临时文件的解决方案不适合。
3个回答

4

我不确定我完全理解,您想要读取InputStream一次 (不是真的两次,这有点不干净,因为如果只有日志流而没有您正在解析的流发生错误怎么办?) 然后简单地记录和解析相同的InputStream?

如果您上面的情况是这样的,下面是伪代码展示解决方案:

InputStream is=...;
byte[] bytes=new byte[1028];
while(is.read(bytes)!=-1) {
log(bytes); //call function to log
parse(bytes);//call function to parse
}

更好的同时记录日志和录制的方法是为这两个方法创建一个新的Thread/Runnable,启动它们并使用(thread.join();)等待它们返回:
InputStream is=...;
byte[] bytes=new byte[1028];
while(is.read(bytes)!=-1) {
Thread t1=new Thread(new Runnable() {
        @Override
        public void run() {
          log(bytes); //call function to log
        }
    });
Thread t2=new Thread(new Runnable() {
        @Override
        public void run() {
           parse(bytes);//call function to parse
        }
    });
     t1.start();
     t2.start();
try {
     t1.join();
     t2.join();
    }catch(Exception ex) {
      ex.printStackTrace();
    }
}

我想两次获取完整的流内容(内容为JSON格式的字符串):第一次只是为了将其写入日志,第二次则是为了解析响应。 - Dmitriy Tarasov
1
无论如何,一旦您将String转换为JSON格式,请将其传递给解码方法,然后将返回的String传递给log()parse()。像我之前提到的和另一个答案所述的那样,重复读取流非常糟糕。 - David Kroukamp
代码有缺陷。它忽略了read()的结果,因此有可能在每个缓冲区末尾处理垃圾数据。 - user207421
那代码都编译不通过。正确的写法应该是 log(bytes, 0, count); 以及 parse(bytes, 0, count); 其中的 countread() 方法返回的 int 类型结果。 - user207421
我不确定我理解了,看一下这里的文档:http://docs.oracle.com/javase/1.4.2/docs/api/java/io/InputStream.html#read%28byte[]%29 - David Kroukamp
我熟悉Java.io的Javadoc。你到底不理解什么? - user207421

2

您永远不需要两次读取输入流。在读取时记录它。


0

如果您事先不知道流的潜在大小(或者它太大而无法放入Stringbyte[]中),那么我建议使用HttpURLConnectionInputStream来记录(如果需要,可以记录到单独的文件中),并且我会使用日志文件进行解析。

这可能不是复制InputStream最有效的方法,但从内存方面考虑,这可能是最安全的方法之一。


谢谢你的回答,但这个解决方案太慢且笨重。 - Dmitriy Tarasov

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