简体   繁体   English

HttpURLConnection两次读取InputStream

[英]HttpURLConnection read InputStream twice

I make a http get request to server via HttpURLConnection and I need to read response ( InputStream ) twice: for logging purposes and for parsing response. 我通过HttpURLConnection向服务器发出一个http get请求,并且我需要读取两次响应( InputStream ):用于记录目的和用于解析响应。 The returned InputStraem is instance of org.apache.harmony.luni.internal.net.www.protocol.http.ChunkedInputStream which doesn't support marking ( is.markSupported() return false ). 返回的InputStraem是不支持标记的org.apache.harmony.luni.internal.net.www.protocol.http.ChunkedInputStream实例( is.markSupported()返回false )。

Therefore I can't mark() and reset() stream and after writing response in log I can't parse it. 因此,我无法mark()reset()流,并且在日志中写入响应后,我无法解析它。 Ofcourse I can read response once into String or something else, log them and later parse. 当然,我可以一次将响应读入String或其他内容,将其记录下来,然后进行解析。 But when i'm working with streams i'm avoiding potentially OutOfMemomryError because streams deals with buffering instead of me. 但是,当我使用流时,我会避免潜在的OutOfMemomryError因为流而不是我处理缓冲。

What is the best solution in this case which will keep the benefits of using streams and help to achieve the desired result: the simultaneous recording into the log and parsing response? 在这种情况下最好的解决方案是什么,它将保留使用流的好处并有助于实现所需的结果:同时记录到日志和解析响应中?

EDIT: Solution with writing response into temporary file isn't appropriate 编辑:将响应写入临时文件的解决方案不合适

I'm not sure I fully understand, you'd like to read the InputStream once (not really twice that's a bit unclean IMO, because what if an error occurs only on the log stream and not the stream you are parsing?) and then simply log and parse the same InputStream ? 我不确定我是否完全理解,您想读取一次InputStream (不是两次,这确实有点不干净IMO,因为如果仅在日志流而不是您正在解析的流上发生错误怎么办?)然后只需记录并解析相同的InputStream

If the above is the case here pseudo to show the solution: 如果以上是这种情况,此处为伪以显示解决方案:

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

even better for simultaneous logging and recording would be creating a new Thread / Runnable for both methods, starting them and wait for them to return using ( thread.join(); ): 对于同时记录和记录更好的方法是为这两种方法创建一个新的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();
    }
}

You should never need to read an input stream twice. 您永远不需要读取输入流两次。 Log it as you read it. 阅读时记录下来。

If you don't know in advance the potential size of the stream (or if it's too big to be put in a String or a byte[] ), then I would use the InputStream of the HttpURLConnection to log (possibly in a separate file if you need to) and I would use the log file for the parsing purpose. 如果您事先不知道流的潜在大小(或者它太大而无法放入Stringbyte[] ),那么我将使用HttpURLConnectionInputStream进行记录(可能在单独的文件中) (如果需要),我将使用日志文件进行解析。

This is probably not the most efficient way of duplicating an InputStream but probably one of the safest memory wise. 这可能不是复制InputStream的最有效方法,但可能是最安全的内存方式之一。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM