Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why can I only read 2048 bytes at a time from an okhttp.Response InputStream?

I am downloading a file using an OkHttp GET request:

import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
...
OkHttpClient okClient = new OkHttpClient();
Request request = Request.Builder().url(url).get();
Response response = okClient.newCall(request).execute();

I read from the response body and decorating it with a BufferedInputStream, with a buffer size of 4096:

BufferedInputStream in = new BufferedInputStream(response.body().byteStream(), 4096);

However, when I try to read from the buffer, the first read returns 1179 bytes. After that, I am only able to read 2048 bytes at a time:

byte[] buffer = new byte[4096];
while (true) {
    int bytesRead = in.read(buffer); //bytesRead is always 2048, except the first read
    if (bytesRead == -1) break;
}

Several related questions:

  1. What could be causing the first read to return 1179 bytes? Some sort of file header?
  2. Why are reads from the InputStream being paged to a size of 2048 bytes, instead of the value specified by the BufferedInputStream wrapper?
  3. Is there a way to configure the OkHttpClient to read more than 2048 bytes from the buffer?
like image 776
weefbellington Avatar asked Sep 24 '14 17:09

weefbellington


1 Answers

What could be causing the first read to return 1179 bytes? Some sort of file header?

The HTTP header is 869 bytes for the response you are reading.

Why are reads from the InputStream being paged to a size of 2048 bytes, instead of the value specified by the BufferedInputStream wrapper?

You'd have to go digging in BufferedInputStream to find out why it's not joining two pages together.

The InputStream from OkHttp is handing 2048 chunks because it uses a pool of them to save allocations.

Is there a way to configure the OkHttpClient to read more than 2048 bytes from the buffer?

No.


Depending on what you are doing, you'll generally have a much better time using the BufferedSource from response.body().source() rather than using BufferedInputStream. You can learn more about them on the Okio repo.

like image 177
Jake Wharton Avatar answered Sep 28 '22 04:09

Jake Wharton