若是用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()方法就返回實際文件的大小,這個方法實際上是經過文件描述符獲取文件的總大小,而並非事先將磁盤上的文件數據所有讀入流中,再獲取文件總大小。
但願能用心去體會一下,選擇性使用