zoukankan      html  css  js  c++  java
  • [Android Pro] 关于inputStream.available()方法获取文件的总大小

    reference to : http://hold-on.iteye.com/blog/1017449

     如果用inputStream对象的available()方法获取流中可读取的数据大小,通常我们调用这个函数是在下载文件或者对文件进行其他处理时获取文件的总大小。

     以前在我们初学File和inputStream和outputStream时,有需要将文件从一个文件夹复制到另一个文件夹中,这时候我们用的就是inputStream.available()来获取文件的总大小,而且屡试不爽。

    但是当我们要从网络URL中下载一个文件时,我们发现得到的数值并不是需要下载的文件的总大小。

    好吧。我们看看JDK文档中怎么解释。

    available

    public int available()
                  throws IOException
    返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数。下一个调用可能是同一个线程,也可能是另一个线程。一次读取或跳过此估计数个字节不会受阻塞,但读取或跳过的字节数可能小于该数。

    注意,有些 InputStream 的实现将返回流中的字节总数,但也有很多实现不会这样做。试图使用此方法的返回值分配缓冲区,以保存此流所有数据的做法是不正确的。

    如果已经调用 close() 方法关闭了此输入流,那么此方法的子类实现可以选择抛出 IOException

    InputStreamavailable 方法总是返回 0

    此方法应该由子类重写。

    返回: 可以不受阻塞地从此输入流读取(或跳过)的估计字节数;如果到达输入流末尾,则返回 0抛出: IOException - 如果发生 I/O 错误。

    inputStream 源代码

        /** 
            * Returns the number of bytes that are available before this stream will 
            * block. This implementation always returns 0. Subclasses should override 
            * and indicate the correct number of bytes available. 
            *  
            * @return the number of bytes available before blocking. 
            * @throws IOException 
            *             if an error occurs in this stream. 
            * @since Android 1.0 
            */  
          public int available() throws IOException {  
               return 0;  
           }

     这里返回的是 0 值。

    所以说要从网络中下载文件时,我们知道网络是不稳定的,也就是说网络下载时,read()方法是阻塞的,说明这时我们用

    inputStream.available()获取不到文件的总大小。

     

    但是从本地拷贝文件时,我们用的是FileInputStream.available(),难道它是将先将硬盘中的数据先全部读入流中?

    然后才根据此方法得到文件的总大小?

    好吧,我们来看看FileInputStream源代码吧

        /** 
            * Returns the number of bytes that are available before this stream will 
            * block. This method always returns the size of the file minus the current 
            * position. 
            *  
            * @return the number of bytes available before blocking. 
            * @throws IOException 
            *             if an error occurs in this stream. 
            * @since Android 1.0 
            */  
           @Override  
           public int available() throws IOException {  
               openCheck();  
          
               // BEGIN android-added  
          
               // Android always uses the ioctl() method of determining bytes  
               // available. See the long discussion in  
               // org_apache_harmony_luni_platform_OSFileSystem.cpp about its  
               // use.  
          
              return fileSystem.ioctlAvailable(fd.descriptor);
               // END android-added   
          
               // BEGIN android-deleted  
               // synchronized (repositioningLock) {  
               //     // stdin requires special handling  
               //     if (fd == FileDescriptor.in) {  
               //         return (int) fileSystem.ttyAvailable();  
               //     }  
               //  
               //     long currentPosition = fileSystem.seek(fd.descriptor, 0L,  
               //             IFileSystem.SEEK_CUR);  
               //     long endOfFilePosition = fileSystem.seek(fd.descriptor, 0L,  
               //             IFileSystem.SEEK_END);  
               //     fileSystem.seek(fd.descriptor, currentPosition,  
               //             IFileSystem.SEEK_SET);  
               //     return (int) (endOfFilePosition - currentPosition);  
               // }  
               // END android-deleted  
           }  

    这里重写了inputStream中的available()方法

     

    关键是:fileSystem.ioctlAvailable(fd.descriptor);

    调用了FileSystem这是java没有公开的一个类,JavaDoc API没有。
    其中

    fileSystem 是一个IFileSystem对象,IFileSySTEM是java没有公开的一个类,JavaDoc API中没有;

    fd是一个FileDescriptor对象,即文件描述符

    说明这句代码应该是通过文件描述符获取文件的总大小,而并不是事先将磁盘上的文件数据全部读入流中,再获取文件总大小

     

    搞清楚了这些,但是我们的主要问题没有解决,怎么获得网络文件的总大小?

    我想原理应该都差不多,应该也是通过一个类似文件描述符的东西来获取。

     网络下载获取文件总大小的代码:

    HttpURLConnection httpconn = (HttpURLConnection)url.openConnection();  
    httpconn.getContentLength();

     我们再来看看httpconn.getContentLength();

    /** 
     * Gets the content length in bytes specified by the response header field 
     * {@code content-length} or {@code -1} if this field is not set. 
     *  
     * @return the value of the response header field {@code content-length}. 
     * @since Android 1.0 
     */  
    public int getContentLength() {  
        return getHeaderFieldInt("Content-Length", -1);
    } 

    关键:getHeaderFieldInt("Content-Length", -1);

    意思是从http预解析头中获取“Content-length”字段的值

    其实也是类似从文件描述符中获取文件的总大小

  • 相关阅读:
    【转】虚拟机 NAT网络设置
    [转载]应用 Valgrind 发现 Linux 程序的内存问题
    Visual Studio 代码格式化插件(等号自动对齐、注释自动对齐等)
    【转】链接任意目录下库文件(解决错误“/usr/bin/ld: cannot find -lxxx”
    C语言实现封装、继承和多态
    美国专利搜索网站
    【转】基于OCS实现高速缓存
    【转】防止网页被搜索引擎、爬虫和网页采集器收录或克隆复制的方法汇总
    [转]机器学习和计算机视觉----数学基础
    [转]机器学习与数据挖掘的学习路线图
  • 原文地址:https://www.cnblogs.com/0616--ataozhijia/p/4973102.html
Copyright © 2011-2022 走看看