Чтение HttpURLConnection InputStream — ручной буфер или BufferedInputStream?

При чтении InputStream HttpURLConnection есть ли какая-либо причина использовать одно из следующего вместо другого? Я видел, как оба используются в примерах.

Ручная буферизация:

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

EDIT Я все еще новичок в HTTP в целом, но одно соображение, которое приходит на ум, заключается в том, что если я использую постоянное HTTP-соединение, я не могу просто читать, пока входной поток не станет пустым, верно? В этом случае мне не нужно было бы читать длину сообщения и просто читать входной поток для этой длины?

И точно так же, если НЕ используется постоянное соединение, является ли код, который я включил, на 100% пригодным для правильного чтения потока?


person stormin986    schedule 08.05.2010    source источник
comment
Что такое ByteArrayBuffer? Но нет никакой причины иметь дело с отдельными байтами, когда вы могли бы иметь дело с массивами байтов.   -  person user207421    schedule 29.09.2017


Ответы (4)


Я рассказываю о хорошем способе сделать это в своем блоге в статье об использовании JSON в Android. 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());
     }
}
person Andrew    schedule 20.07.2010
comment
Есть одно определенное, но нужно исправить: вы всегда должны указывать кодировку, используемую для преобразования байтов в строку (new String(baf.toByteArray(), UTF-8). - person StaxMan; 20.10.2010

Что касается постоянных HTTP-соединений, все наоборот. Вы должны читать все из входного потока. В противном случае HTTP-клиент Java не будет знать, что HTTP-запрос завершен и соединение сокета можно использовать повторно.

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

Чем вы можете помочь с Keep-Alive?

Не разрывайте соединение, игнорируя тело ответа. Это может привести к незанятым соединениям TCP. Это нужно собирать мусор, когда на них больше не ссылаются.

Если getInputStream() успешно возвращает значение, прочитайте все тело ответа.

person Robert    schedule 19.06.2010

Используйте первый - последний не имеет реальных преимуществ по сравнению с первым и немного медленнее; чтение побайтно неэффективно, даже если оно буферизовано (хотя и ужасно медленно, если не буферизовано). Этот стиль чтения ввода вышел из моды с C; хотя может быть полезно в тех случаях, когда вам нужно найти какой-то конечный маркер.

person StaxMan    schedule 20.10.2010

Только если вы используете методы, специфичные для BufferedInputStream.

person Delan Azabani    schedule 08.05.2010
comment
К вопросу добавлено дополнительное уточнение. - person stormin986; 08.05.2010
comment
Методы, специфичные для BufferedInputStream, такие как какие? Он не экспортирует никакие методы, кроме тех, которые определены InputStream. - person user207421; 29.09.2017