Reading HttpURLConnection InputStream - manual buffer or BufferedInputStream?
Asked Answered
C

4

4

When reading the InputStream of an HttpURLConnection, is there any reason to use one of the following over the other? I've seen both used in examples.

Manual Buffer:

while ((length = inputStream.read(buffer)) > 0) {
    os.write(buf, 0, ret);
}

BufferedInputStream

is = http.getInputStream();
bis = new BufferedInputStream(is);
ByteArrayBuffer baf = new ByteArrayBuffer(50);

int current = 0;
while ((current = bis.read()) != -1) {
     baf.append(current);
}

EDIT I'm still new to HTTP in general but one consideration that comes to mind is that if I am using a persistent HTTP connection, I can't just read until the input stream is empty right? In that case, wouldn't I need to read the message length and just read the input stream for that length?

And similarly, if NOT using a persistent connection, is the code I included 100% good to go in terms of reading the stream properly?

Celestial answered 8/5, 2010 at 6:26 Comment(1)
What is ByteArrayBuffer? But there is never any reason to deal in single bytes when you could be dealing in byte arrays.Thesaurus
H
5

I talk about a good way to do it on my blog in a post about using JSON in android. http://blog.andrewpearson.org/2010/07/android-why-to-use-json-and-how-to-use.html. I will post the relevant part of the relevant post below (the code is pretty generalizable):

InputStream in = null;
String queryResult = "";
try {
     URL url = new URL(archiveQuery);
     HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
     HttpURLConnection httpConn = (HttpURLConnection) urlConn;
     httpConn.setAllowUserInteraction(false);
     httpConn.connect();
     in = httpConn.getInputStream();
     BufferedInputStream bis = new BufferedInputStream(in);
     ByteArrayBuffer baf = new ByteArrayBuffer(50);
     int read = 0;
     int bufSize = 512;
     byte[] buffer = new byte[bufSize];
     while(true){
          read = bis.read(buffer);
          if(read==-1){
               break;
          }
          baf.append(buffer, 0, read);
     }
     queryResult = new String(baf.toByteArray());
     } catch (MalformedURLException e) {
          // DEBUG
          Log.e("DEBUG: ", e.toString());
     } catch (IOException e) {
          // DEBUG
          Log.e("DEBUG: ", e.toString());
     }
}
Hatten answered 20/7, 2010 at 20:39 Comment(1)
There is one definite but to fix: you should always specify encoding to use for converting bytes to String (new String(baf.toByteArray(), "UTF-8").Hardener
S
2

Regarding persistent HTTP connections it is just the opposite. You should read everything from the input stream. Otherwise the Java HTTP client does not know that the HTTP request is complete and the socket connection can be reused.

See http://java.sun.com/javase/6/docs/technotes/guides/net/http-keepalive.html:

What can you do to help with Keep-Alive?

Do not abandon a connection by ignoring the response body. Doing so may results in idle TCP connections. That needs to be garbage collected when they are no longer referenced.

If getInputStream() successfully returns, read the entire response body.

Skipjack answered 19/6, 2010 at 16:49 Comment(0)
H
0

Use former -- latter has no real benefits over first one, and is bit slower; reading things byte by byte is inefficient even if buffered (although horribly slow when not buffered). That style of reading input went out of vogue with C; although may be useful in cases where you need to find an end marker of some sort.

Hardener answered 20/10, 2010 at 16:9 Comment(0)
C
-1

Only if you're using the BufferedInputStream-specific methods.

Cryptomeria answered 8/5, 2010 at 6:31 Comment(2)
Further clarification added to question.Celestial
The BufferedInputStream-specific methods such as what? It doesn't export any methods other than those defined by InputStream.Thesaurus

© 2022 - 2024 — McMap. All rights reserved.