`
hold_on
  • 浏览: 455705 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

关于inputStream.available()方法获取下载文件的总大小

    博客分类:
  • java
阅读更多

 

 

 如果用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); //$NON-NLS-1$
    }

 

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

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

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

分享到:
评论
2 楼 sd1132632 2012-03-09  
真心谢谢LZ的文章,解决了我棘手的问题
1 楼 懒无极限 2011-08-09  
受教了!最近刚刚遇到类似问题,这下明白了。

相关推荐

    Java 实例 - 获取文件大小源代码-详细教程.zip

    总结来说,Java提供了多种方式来获取文件大小,无论是通过`File`类的`length()`方法,还是使用`Files`类的`size()`方法,都能满足日常开发需求。在实际应用中,根据具体场景选择合适的方法,并注意异常处理和性能...

    IO流文档InputStream / OutputStream

    在IO流中, mark()和reset()方法用于标记流中的位置,skip()方法用于跳过流中的某些字节,而available()方法用于获取流中的可用字节数。close()方法用于关闭流,释放系统资源。 在Java中,IO流还可以用于实现对象...

    Java文件下载的几种方式

    设置HTTP响应头,告知浏览器以附件形式下载,并指定文件名和文件大小。最后,通过`BufferedOutputStream`将字节数组写入到HTTP响应中,完成文件的下载。 #### 2. 网络文件下载 网络文件下载涉及从网络资源读取文件...

    java response 下载文件方法

    ### Java Response 下载文件方法详解 在Web应用开发过程中,经常需要实现文件的上传与下载功能。其中,通过`java response`实现文件下载是常见需求之一。本文将深入解析如何利用Java中的`HttpServletResponse`对象...

    图片文件上次,获取图片文件实际类型

    // 检查文件上传的大小,文件不能大于2MB 2097152 if (s > num) { return false; } bis = new BufferedInputStream(fis); FileOutputStream fos = new FileOutputStream(newFile); bos...

    android 读取 assets 文件夹下的音频

    请注意,`assets`文件夹下的文件大小限制没有明确的规定,但根据描述中提到的,可能存在超过1MB的音频文件无法读取的问题。这可能是由于设备内存限制、流处理不当或其他因素导致的。因此,对于大文件,最好分块读取...

    狂刷Android范例之一:ReadAsset

    // 获取文件大小 inputStream.read(buffer); // 读取文件内容到缓冲区 String content = new String(buffer, "UTF-8"); // 将字节流转换为字符串,注意设置编码格式 Log.d("ReadAsset", "文件内容: " + content)...

    java 使用流下载文件

    随后,获取文件的全部内容到一个字节数组中: ```java byte[] buffer = new byte[ins.available()]; ins.read(buffer); ``` 其中`ins.available()`返回的是当前输入流中可用的字节数。通过调用`read`方法,将文件...

    javaweb FileUpload 图片文件上传示例源码下载

    6. **文件大小验证**: `stream.available()`方法可以获取文件大小,但需要注意,它可能返回的是一个估计值。如果需要精确的大小,可以先将文件写入临时文件,然后获取其长度。 7. **保存文件**: `saveFile`方法将...

    FileOutputStream向文件进行输出.txt

    - **读取数据**: 可以通过`available()`方法获取可用字节数,然后创建相应大小的字节数组来读取数据。 综上所述,以上示例代码展示了如何使用`FileOutputStream`向文件写入数据、追加数据以及如何获取资源文件的...

    Android文件读取[定义].pdf

    使用`available()`方法可以预估文件大小,然后分配内存缓冲区进行读取。 - **字符串转换:** ```java res = EncodingUtils.getString(buffer, "UTF-8"); ``` 读取后的字节数组需要转换为字符串。这里使用`...

    安卓读取小文件 进度条同步方法

    在Android开发中,读取小文件并实现进度条同步是一个常见的需求,特别是在处理大文件时,用户界面的反馈显得尤为...在实际开发中,根据具体需求,可能还需要考虑错误处理、文件大小的动态获取、内存管理等更多细节。

    java文件上传下载

    文件下载是指用户可以通过Web应用从服务器获取文件并保存到本地计算机的过程。通常情况下,用户会通过点击一个链接或按钮触发文件下载操作。 #### 五、文件下载的关键技术要点 **1. HTTP响应头配置** - `Content-...

    java 文件读写功能

    // 获取文件指针的位置 raf.seek(pos); // 将文件指针定位到pos位置 System.out.println(raf.readLine()); // 按行读取内容 pos += 50; // 移动文件指针位置 raf.seek(pos); // 再次定位文件指针 } raf.close...

    Android-tensorflow在android上实现物体识别

    fileChannel.transferFrom(inputStream, 0, inputStream.available()); inputStream.close(); fileChannel.close(); Interpreter interpreter = new Interpreter(loadModelFile()); ``` 4. **图像处理**: 物体识别...

    strust文件上传

    System.out.println( streamIn.available()+"文件大小byte"); //这个是io包下的上传文件类 File uploadFile = new File(dir); //指定上传文件的位置 if (!uploadFile.exists() || uploadFile == null) { //判断...

    java下载代码

    代码片段中使用了`fileService.obtainEntity()`方法来根据`FileSourceId`获取文件源信息。这个步骤是确保我们有正确的文件路径和相关信息。 #### 2. 文件路径处理 ```java String downLoadPath = request....

    java入门之io包

    它允许我们创建、删除、重命名文件,并获取文件的属性,如路径、大小、最后修改时间等。例如,以下代码展示了如何使用`File`类的基本操作: ```java File file = new File("example.txt"); System.out.println(...

    java中文件的MD5和SHA-1的使用

    System.out.println("文件大小:" + in.available() / 1024 / 1024 + " M"); in.close(); long time1 = System.currentTimeMillis(); System.out.println("MD5 为:" + MD5Util.getFileMD5(file)); long time2 =...

    Android 数据存储之 FileInputStream 工具类及FileInputStream类的使用

    通过`available()`方法获取文件的大小,创建相应长度的缓冲区,然后读取文件内容到缓冲区。读取完成后,将字节数组转换回字符串并打印,最后关闭流。如果需要解析特定格式的数据,如JSON或XML,可以在读取后进行相应...

Global site tag (gtag.js) - Google Analytics