【问题标题】:HttpURLConnection read InputStream twiceHttpURLConnection 两次读取 InputStream
【发布时间】:2012-09-10 11:47:06
【问题描述】:

我通过 HttpURLConnection 向服务器发出 http get 请求,我需要读取响应 (InputStream) 两次:用于记录目的和解析响应。返回的InputStraem 是不支持标记的org.apache.harmony.luni.internal.net.www.protocol.http.ChunkedInputStream 的实例(is.markSupported() 返回false)。

因此我不能mark()reset() 流并且在日志中写入响应后我无法解析它。当然,我可以将响应读入String 或其他内容,记录它们并稍后解析。但是当我使用流时,我可能会避免OutOfMemomryError,因为流处理缓冲而不是我。

在这种情况下,什么是最好的解决方案,既能保留使用流的好处,又有助于实现预期的结果:同时记录到日志和解析响应?

编辑:将响应写入临时文件的解决方案不合适

【问题讨论】:

    标签: java android inputstream httpurlconnection


    【解决方案1】:

    我不确定我是否完全理解,你想读一次InputStream(不是真的两次,这有点不干净IMO,因为如果错误只发生在日志流上而不是你所在的流上怎么办解析?),然后简单地记录并解析相同的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 格式的字符串):第一次 - 只是将其写入日志,第二次 - 解析响应
    • 无论哪种方式,一旦您拥有 JSON 格式的 String,将其传递给 解码它的方法,然后将返回的 String 传递给 log() 和 @ 987654332@。正如我提到的和另一个答案一样,阅读两次 Stream 真的很糟糕
    • 代码有缺陷。它忽略了read()的结果,所以它很容易在每个缓冲区的末尾处理垃圾。
    • 那甚至无法编译。它应该是log(bytes, 0, count);parse(bytes, 0, count);,其中countint 方法的int 结果。
    • 我不确定我是否明白,看看这里的文档:docs.oracle.com/javase/1.4.2/docs/api/java/io/…
    【解决方案2】:

    您永远不需要读取输入流两次。阅读时记录下来。

    【讨论】:

      【解决方案3】:

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

      这可能不是复制InputStream 的最有效方式,但可能是最安全的内存方式之一。

      【讨论】:

      • 感谢您的回答,但是这个解决方案太慢而且太笨重(
      猜你喜欢
      • 2020-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-24
      • 1970-01-01
      • 2016-01-02
      • 2012-10-28
      • 2011-08-10
      相关资源
      最近更新 更多