2017-09-29 62 views
0

我正在嘗試在我的Android應用程序中使用HttpUrlConnectionAsyncTask中從網絡讀取文件。爲什麼BufferedInputStream每次最多讀取2048個字節?

雖然我注意到文件下載的工作速度比它應該慢一點,因爲我使用的網絡速度更快。

所以我檢查發現,BufferedInputStream對象每次最多隻能讀取2048個字節。沒有我設置的緩衝區大小。即使BufferedInputStream的內部默認緩衝區大小也是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個字節。

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 

我試過多個大於2048的緩衝區大小,但沒有任何東西似乎改變了閱讀速率。

這是什麼原因?我可以更改它以獲取指定緩衝區大小的數據嗎?

+2

你確定源代碼提供足夠的連續字節來讀取它們,因爲? 'read'的JavaDoc明確指出何時中止讀取更多內容,是否調試過它來檢查哪些檢查失敗? – Tom

+0

我嘗試了不同的來源,所以不確定它是否受限於來源。我沒有嘗試在讀取方法內部進行調試。 –

回答

5

因爲這是所有準備在任何時候都可以閱讀的,由於它被髮送的方式。在這方面你什麼都做不了,除了可能讀取次數較少;-)沒有特別的理由一次只需要8192個字節:在一個正確寫入的讀取循環中,你不應該關心它是一個字節還是一個兆字節,或者無論你的緩衝區大小是多少read()的合同僅僅是它傳送'至少一個字節',除非發生異常或流結束。

+1

簡單明瞭,幾乎可以肯定是正確的,既有文獻記錄,又有源源不絕的作品。 –

+0

所以,這意味着它被阻止來自url源? –

+0

@AkashRaghav「因爲發送方式」的部分內容你不理解嗎? – EJP

相關問題