Java 为什么BufferedInputStream一次最多读取2048字节?

Java 为什么BufferedInputStream一次最多读取2048字节?,java,android,io,httpurlconnection,bufferedinputstream,Java,Android,Io,Httpurlconnection,Bufferedinputstream,我正在尝试使用Android应用程序中的AsyncTask中的HttpUrlConnection从网络读取文件 虽然我注意到一件事,文件下载工作比它应该有点慢,因为我使用的网络速度更快 因此,我检查并发现BufferedInputStream对象一次最多只能读取2048字节。没有我设置的缓冲区大小。甚至BufferedInputStream的内部默认缓冲区大小也是8192字节 total bytes read : 1748 buffer size : 8192 total bytes read

我正在尝试使用Android应用程序中的
AsyncTask
中的
HttpUrlConnection
从网络读取文件

虽然我注意到一件事,文件下载工作比它应该有点慢,因为我使用的网络速度更快

因此,我检查并发现
BufferedInputStream
对象一次最多只能读取2048字节。没有我设置的缓冲区大小。甚至
BufferedInputStream
的内部默认缓冲区大小也是8192字节

total bytes read : 1748 buffer size : 8192
total bytes read : 2048 buffer size : 8192
total bytes read : 2048 buffer size : 8192
total bytes read : 2048 buffer size : 8192
total bytes read : 1988 buffer size : 8192
我在这里添加代码以供参考

private class DownloadFileTask extends AsyncTask<String, Integer, String> {

  @Override
  protected String doInBackground(String... params) {
    HttpURLConnection connection = null;
    BufferedInputStream input = null;
    OutputStream output = null;
    int lengthOfFile;
    int totalBytesDownloaded = 0;
    int count;
    final int bufferSize = 8 * 1024; // 8KB
    try {
      // Create the URL
      URL url = new URL(params[0]);
      // Open connection
      connection = (HttpURLConnection) url.openConnection();
      // Get the file length
      lengthOfFile = connection.getContentLength();
      // Input stream to read file - with bufferSize buffer
      input = new BufferedInputStream(connection.getInputStream(), bufferSize);

      if (isCancelled()) {
        return null;
      }
      // Output stream to write file
      File parentFile = TestUtil.getStorageDir(getApplicationContext(),Constants.EXTRA_DIRECTORY_NAME_TEST_MEDIA);
      File file = new File(parentFile.getAbsolutePath() + "/" + "zipFile");

      if (!file.exists()) {
        file.getParentFile().mkdirs();
      }

      // Create the file o/p stream
      output = new FileOutputStream(file.getAbsolutePath());

      // Create the buffer o/p stream for performance
      BufferedOutputStream bos = new BufferedOutputStream(output, bufferSize);

      // Buffer
      byte data[] = new byte[bufferSize];
      while ((count = input.read(data, 0, bufferSize)) != -1 && !isCancelled()) {
        // Increase the total bytes downloaded
        totalBytesDownloaded += count;
        Log.d("DEBUG_LOG","total bytes read : " + count + " buffer size : " + data.length);

        // Write the data to the o/p buffer
        bos.write(data, 0, count);
      }

      // Publish update again since the loop may have skipped the last publish update
      publishProgress(totalBytesDownloaded, lengthOfFile);

      // Flush the o/p stream
      output.flush();
      return file.getAbsolutePath();
    } catch (SocketException | SocketTimeoutException e) {
      handler.sendEmptyMessage(Constants.CASE_INTERNET_FAILURE);
      Log.e("DEBUG_LOG", e);
    } catch (IOException e) {
      Log.e("DEBUG_LOG","Error: " + e.getMessage());
    } finally {
      // closing streams
      if (output != null) {
        try {
          output.close();
        } catch (IOException e) {
          AMLog.e(e);
        }
      }
      if (input != null) {
        try {
          input.close();
        } catch (IOException e) {
          AMLog.e(e);
        }
      }
      if (connection != null) {
        connection.disconnect();
      }
    }
    return null;
  }

  @Override
  protected void onProgressUpdate(Integer... values) {
    int percentage = (values[0] * 100) / values[1] ;
    textDownloadSizeMb.setText(String.format(getString(R.string.label_download_mb), String.valueOf(values[0]), String.valueOf(values[1])));
    textDownloadPercent.setText(String.format(Locale.getDefault(), "%s%s", percentage, " %"));
    progressBar.setMax(values[1]);
    progressBar.setProgress(values[0]);
  }

  @Override
  protected void onPostExecute(String value) {
  }
}
我尝试过多个大于2048的缓冲区大小,但似乎没有改变读取速率


这背后的原因是什么?我可以更改它以获取指定缓冲区大小的数据吗?

因为由于发送方式的不同,在任何时候都可以读取这些数据。在这一点上你无能为力,除了少读;-)一次需要8192字节没有什么特别的原因:在一个正确写入的读循环中,您不应该关心它是一个字节还是一个兆字节,或者不管您的缓冲区大小如何。
read()
的契约仅仅是它传输“至少一个字节”,除非出现异常或流结束。

因为由于发送方式的不同,这就是任何时候都可以读取的内容。在这一点上你无能为力,除了少读;-)一次需要8192字节没有什么特别的原因:在一个正确写入的读循环中,您不应该关心它是一个字节还是一个兆字节,或者不管您的缓冲区大小如何。
read()
的契约仅仅是它传输“至少一个字节”,除非发生异常或流结束。

并且您确信源提供足够的连续字节来读取它们,因为?
read
的JavaDoc清楚地说明了当它中止读取更多内容时,您是否调试过它以检查哪些检查失败?我尝试了不同的源代码,因此不确定它是否受到源代码的限制。我还没有尝试在read方法内部进行调试。您确定源代码提供了足够的连续字节来读取它们,因为?
read
的JavaDoc清楚地说明了当它中止读取更多内容时,您是否调试过它以检查哪些检查失败?我尝试了不同的源代码,因此不确定它是否受到源代码的限制。我没有尝试在read方法内部进行调试。鉴于文档和sneeky对源代码的窥视,简单、明显且几乎肯定是正确的。因此,这意味着它被url源阻止了?@AkashRaghav“由于发送方式”的哪一部分您不明白吗?@AkashRaghav它不一定被“阻止”--就像在“主动变慢”中一样--这可能就是为您的数据服务的任何东西的编写方式。@AkashRaghav这是一个完全合理的问题。我想知道你是否理解我答案中的一个词,或者你只是想让我重写它。简单,明显,几乎可以肯定是对的,考虑到文档和斯内基对来源的窥视。所以,这意味着它正从url源被阻止?@AkashRaghav“由于它的发送方式”的哪一部分您不明白吗?@AkashRaghav它不一定被“阻止”--就像“主动变慢”--这可能只是服务于您的数据的编写方式。@AkashRaghav这是一个完全合理的问题。我想知道你是否理解我答案中的一个词,或者你只是想让我改写它。