若是用inputStream对象的available()方法获取流中可读取的数据大小,一般咱们调用这个函数是在下载文件或者对文件进行其余处理时获取文件的总大小。html
之前在咱们初学File和inputStream和outputStream时,有须要将文件从一个文件夹复制到另外一个文件夹中,这时候咱们用的就是inputStream.available()来获取文件的总大小,并且屡试不爽。java
可是当咱们要从网络URL中下载一个文件时,咱们发现获得的数值并非须要下载的文件的总大小。网络
好吧。咱们看看JDK文档中怎么解释。函数
public int available() throws IOException
返回此输入流下一个方法调用能够不受阻塞地今后输入流读取(或跳过)的估计字节数。下一个调用多是同一个线程,也多是另外一个线程。一次读取或跳过此估计数个字节不会受阻塞,但读取或跳过的字节数可能小于该数。url
注意,有些 InputStream
的实现将返回流中的字节总数,但也有不少实现不会这样作。试图使用此方法的返回值分配缓冲区,以保存此流全部数据的作法是不正确的。spa
若是已经调用 close()
方法关闭了此输入流,那么此方法的子类实现能够选择抛出 IOException
。线程
类 InputStream
的 available
方法老是返回 0
。此方法应该由子类重写。code
返回:orm
能够不受阻塞地今后输入流读取(或跳过)的估计字节数;若是到达输入流末尾,则返回 0
。htm
抛出:
IOException
- 若是发生 I/O 错误。
咱们来看看inputStream:
inputStream 源代码
public int available() throws IOException { return 0; }
这里返回的是 0 值。
因此说要从网络中下载文件时,咱们知道网络是不稳定的,也就是说网络下载时,read()方法是阻塞的,说明这时咱们用
inputStream.available()获取不到文件的总大小。
可是从本地拷贝文件时,咱们用的是FileInputStream.available(),难道它是将先将硬盘中的数据先所有读入流中?
而后才根据此方法获得文件的总大小?
好吧,咱们来看看FileInputStream源代码吧
public int available() throws IOException { openCheck(); return fileSystem.ioctlAvailable(fd.descriptor);</span> }
这里重写了inputStream中的available()方法
关键是:fileSystem.ioctlAvailable(fd.descriptor);
调用了FileSystem这是java没有公开的一个类,JavaDoc API没有。
其中
fileSystem 是一个IFileSystem对象,IFileSySTEM是java没有公开的一个类,JavaDoc API中没有;
fd是一个FileDescriptor对象,即文件描述符
说明这句代码应该是经过文件描述符获取文件的总大小,而并非事先将磁盘上的文件数据所有读入流中,再获取文件总大小
搞清楚了这些,可是咱们的主要问题没有解决,怎么得到网络文件的总大小?
我想原理应该都差很少,应该也是经过一个相似文件描述符的东西来获取。
网络下载获取文件总大小的代码:
Java代码:
HttpURLConnection httpconn = (HttpURLConnection)url.openConnection(); httpconn.getContentLength();//获取文件长度
咱们再来看看httpconn.getContentLength();
Java代码
public int getContentLength() { return getHeaderFieldInt("Content-Length", -1); }
关键:getHeaderFieldInt("Content-Length", -1);
意思是从http预解析头中获取“Content-length”字段的值
其实也是相似从文件描述符中获取文件的总大小
总结:
①若是要从网络中下载文件时,咱们知道网络是不稳定的,也就是说网络下载时,read()方法是阻塞的,说明这时咱们用inputStream.available()获取不到文件的总大小。
此时就须要经过
HttpURLConnection httpconn = (HttpURLConnection)url.openConnection();
httpconn.getContentLength();//获取文件长度
来获取文件的大小。
②若是是本地文件的话,使用inputStream.available()方法就返回实际文件的大小,这个方法实际上是经过文件描述符获取文件的总大小,而并非事先将磁盘上的文件数据所有读入流中,再获取文件总大小。
但愿能用心去体会一下,选择性使用