使用HttpURLConnection读取InputStream时,应该手动缓冲还是使用BufferedInputStream?

4

当读取HttpURLConnection的InputStream时,使用以下哪种方法有什么理由?我在示例中看到两者都被使用。

手动缓冲:

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

缓冲输入流

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

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

编辑 我对HTTP还很陌生,但有一个考虑因素是,如果我正在使用持久的HTTP连接,我不能只读取输入流直到为空,对吗?在这种情况下,我需要读取消息长度,然后仅读取该长度的输入流,对吗?

同样地,如果不使用持久连接,那么我包含的代码在正确读取流方面是否100%可行?


什么是ByteArrayBuffer?但是当你可以处理字节数组时,就没有理由只处理单个字节。 - user207421
4个回答

5

我在一篇关于在Android中使用JSON的博客文章中谈到了一种好的方法。http://blog.andrewpearson.org/2010/07/android-why-to-use-json-and-how-to-use.html。下面是相关文章的相关部分(代码是相当通用的):

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

2
有一个明确的问题需要解决:在将字节转换为字符串时,您应该始终指定要使用的编码(new String(baf.toByteArray(), "UTF-8"))。 - StaxMan

2
关于持久HTTP连接,正好相反。您应该从输入流中读取所有内容。否则,Java HTTP客户端不知道HTTP请求何时完成,套接字连接也无法重用。
请参见http://java.sun.com/javase/6/docs/technotes/guides/net/http-keepalive.html

如何帮助Keep-Alive?

不要通过忽略响应体而放弃连接。这样做可能导致空闲的TCP连接。当它们不再被引用时,需要进行垃圾回收。

如果getInputStream()成功返回,请阅读整个响应主体。


0

使用前者--后者与第一个相比没有真正的好处,并且稍微慢一些;即使是缓冲的,逐字节读取输入也是低效的(尽管在非缓冲时可怕的慢)。这种读取输入的方式已经过时了,虽然在需要查找某种结束标记的情况下可能有用。


-1

只有在使用BufferedInputStream特定的方法时才会返回。


问题已经进一步澄清。 - stormin986
BufferedInputStream 特定的方法有哪些?它没有导出除 InputStream 定义的方法之外的任何方法。 - user207421

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