2010-12-03 87 views

回答

1

Java流中的read(byte[])方法讀取的字節數可能少於請求的字節數。

通過在互聯網上的文件我假設你的意思是一個HTTP URL的內容。

某些HTTP響應不會預先給出Content-Length,也不能像預先分配正確大小的字節數組。

您可能有興趣知道Android上可用的Apache http客戶端庫已經提供了一個輔助方法EntityUtils.toByteArray(),它可以完全獲取URL的內容並將其作爲正確大小的字節數組返回。

下面是使用它的一段代碼:

public byte[] fetchURL(String url) throws IOException, ClientProtocolException { 
     HttpClient httpclient = new DefaultHttpClient(); 
     HttpGet httpget = new HttpGet(url); 
     HttpResponse response = httpclient.execute(httpget); 
     HttpEntity entity = response.getEntity(); 
     return EntityUtils.toByteArray(entity); 
} 

注意閱讀在內存中的整個反應並不總是最好的解決方案。向用戶報告下載進度或遞增解析大文檔可能更好。事實上,響應甚至可能不適合RAM(例如大視頻流)。

1

正常的讀命令會讀取一些字節數直到請求的長度。程序員應該對返回值進行檢查(告訴你讀了多少字節)。還有readFully方法,它強制它讀取所需的全部長度,但是這可能會阻塞很長一段時間,從而阻止您在閱讀大量流的過程中突然中斷。

1

是否有任何理由爲什麼我的字節數組應該只在調用後部分填充?

是的。所以你的android應用程序不需要等待整個流下載,然後從read呼叫返回。

在你的特定用例中,這顯然是一個討厭的東西。在其他用途​​的情況下,它是read行爲這樣一個關鍵要求:

  • 應用程序可能需要啓動處理和交付成果的用戶在遠程服務器仍然是發送數據。

  • 在發送更多數據之前,遠程服務器實際上可能正在等待來自客戶端的某種應用程序級響應。 (如果您使用的是HTTP或FTP,這不適用,但是您正在閱讀的流可能會封裝一個傳輸層Socket流,並且在那個級別上對任何表示層協議細節都沒有任何瞭解。)

的解決方案是:

  • 使用一個循環,並保持閱讀,直到read返回零。
  • 如果您使用的是Apache HttpClient,有許多方法可以獲取響應的全部內容。
  • Apache Commons包含一個IOUtils類,它具有讀取整個流或讀取器的輔助方法。

順便說一下,這種行爲在read(byte[], ...)方法的javadoc中明確指定。

相關問題