2017-09-29 12 views
0

Android 애플리케이션의 AsyncTask에서 HttpUrlConnection을 사용하여 네트워크에서 파일을 읽으려고합니다.왜 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) { 
    } 
} 

버퍼 크기가 8192 바이트 인 반면 읽은 데이터가 2048 바이트보다 클 수 없음을 나타내는 로그의 일부입니다.

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

그리고 소스에서 연속적인 바이트를 읽을 수있을 것이라고 확신합니까? JavaDoc의'read'는 명확하게 더 이상 읽을 것을 중단 할 때 디버깅하여 체크가 실패했는지를 확인합니다. – Tom

+0

다른 소스를 시도 했으므로 소스가 제한적인지 확실하지 않았습니다. read 메서드 내에서 디버깅을 시도하지 않았습니다. –

답변

5

전송되는 방식 때문에 언제든지 읽을 준비가되었습니다. 이 목적을 위해 이것에 관해 할 수있는 일은 없지만, 자주 읽는 것을 제외하고는 ;-) 한 번에 8192 바이트를 쓰는 특별한 이유는 없습니다. 정확하게 쓰여진 읽기 루프에서는 1 바이트인지 메가 바이트인지 상관하지 말아야합니다. 버퍼 크기가 무엇이든간에. read() 계약은 예외 또는 스트림 종료가 발생하지 않는 한 '적어도 하나의 바이트'를 전송한다는 것입니다.

+1

원본과 원본을 모두 볼 수있는 단순하고 명확하며 거의 확실하게 맞습니다. –

+0

그럼, 이것은 URL 소스로부터 차단되고 있다는 뜻입니까? –

+0

@AkashRaghav '보내는 방식으로 인해'어떤 부분을 이해하지 못했습니까? – EJP