在Android上读取表示互联网上文件的输入流时,如果我请求读取文件的整个长度,是否有任何理由为什么我的字节数组只能在调用后被部分填充?
答案 0 :(得分:1)
Java流上的read(byte[])
方法可能读取的字节数少于请求的数量。
通过互联网上的文件我假设您的意思是HTTP网址的内容。
某些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 :(得分:1)
正常读取命令读取一定数量的字节,直到请求的长度。程序员需要检查返回值(它告诉你读取了多少字节)。还有readFully方法强制它读取所请求的整个长度,但是有可能阻塞很长时间,阻止你在读取大流的过程中发生故障。
答案 2 :(得分:1)
有什么理由说我的字节数组只能在调用后部分填充?
是。因此,您的Android应用程序不必等待整个流下载,然后才能从read
调用返回。
在您的特定用例中,这显然是一种麻烦。在其他用例中,read
以这种方式运行是一个关键要求:
当远程服务器仍在发送数据时,应用程序可能需要开始处理并将结果传递给用户。
在发送更多数据之前,远程服务器实际上可能正在等待来自客户端的某种应用程序级别响应。 (如果您使用的是HTTP或FTP,这将不适用。但您正在读取的流可能包含传输层Socket流,并且在该级别上不了解任何表示层协议详细信息。)
解决方案是:
read
返回零。顺便说一下,read(byte[], ...)
方法的javadocs中明确指出了这种行为。