2010-12-03 86 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中明确指定。

相关问题