简体   繁体   中英

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. 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 ).

Therefore I can't mark() and reset() stream and after writing response in log I can't parse it. Ofcourse I can read response once into String or something else, log them and later parse. But when i'm working with streams i'm avoiding potentially OutOfMemomryError because streams deals with buffering instead of me.

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 ?

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(); ):

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.

This is probably not the most efficient way of duplicating an InputStream but probably one of the safest memory wise.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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