解决InputStream.available()获取流大小问题

 更新时间:2023年06月20日 16:46:38   作者:码农的进阶之路  
这篇文章主要介绍了解决InputStream.available()获取流大小问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

InputStream.available()获取流大小问题

近日在学习IOUtils时,模拟从网络上读取数据存放到本地磁盘,想使用InputStream.available()查看流的大小,结果发现得到的大小跟实际生成文件的大小不一致。

上代码:

InputStream in = new URL("http://www.apache.org").openStream();  
System.out.println(in.available()); 
FileOutputStream out = new FileOutputStream("F://1.html");  
//这里返回的i可以认为是流的大小
int i = IOUtils.copy(in, out); 
System.out.println(i);  
IOUtils.closeQuietly(out); 
IOUtils.closeQuietly(in); 

输出结果:

10660
60787

很显然,按照我们之前的理解,这两个输出得到的数据应该是一样的。后一个输出的文件大小是没有问题的,写入到硬盘上就是那么多字节。那么前一个输出的问题到底在哪呢?

通过查看api,发现了些端倪。该方法的描述是这样的:返回可以不受阻塞地从此文件输入流中读取的字节数

如上,由于是从网络中获取数据,由于存在着网络延迟等因素,所以也就不难理解 两次输出不一致了。

当然,如果是读取本地文件的话,这个方法返回的数据大小一般是真实的。因此,如何使用以及要不要用这个方法,得根据具体的场景

若想获取网络中流的总大小,可以借助URLConnection方法

URLConnection openConnection = new URL("http://www.apache.org").openConnection(); 
System.out.println(openConnection.getContentLength());

InputStream.available()使用大坑

问题场景

文件下载功能,需要对原来的文件进行读取再输出到文件或浏览器中,会常用到InputStream.available()方法。

经历过一次系统功能变更升级,需要将文件先下载到本地再响应出去,发现下载的文件不全

百思不得其解,搜索好久资料,查找得知,以备忘记

这个方法可以在读写操作前先得知数据流里有多少个字节可以读取。

  • 需要注意的是,如果这个方法用在从本地文件读取数据时,一般不会遇到问题,
  • 但如果是用于网络操作,就经常会遇到一些麻烦。比如,Socket通讯时,
  • 对方明明发来了1000个字节,但是自己的程序调用available()方法却只得到900,
  • 或者100,甚至是0,感觉有点莫名其妙,怎么也找不到原因。
  • 其实,这是因为网络通讯往往是间断性的,一串字节往往分几批进行发送。
  • 本地程序调用available()方法有时得到0,这可能是对方还没有响应,也可能是对方已经响应了,
  • 但是数据还没有送达本地。对方发送了1000个字节给你,也许分成3批到达,
  • 这你就要调用3次available()方法才能将数据总数全部得到。

所以在进行网络数据传输时候,不能使用InputStream.available(),这个方法导致系统出现长时间暂停状态

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 一篇文章带你入门java方法

    一篇文章带你入门java方法

    这篇文章主要介绍了java基础之方法详解,文中有非常详细的代码示例,对正在学习java基础的小伙伴们有非常好的帮助,需要的朋友可以参考下
    2021-08-08
  • Java JConsole远程连接配置案例详解

    Java JConsole远程连接配置案例详解

    这篇文章主要介绍了Java JConsole远程连接配置案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • MyBatis特殊SQL的执行实例代码

    MyBatis特殊SQL的执行实例代码

    这篇文章主要给大家介绍了关于MyBatis特殊SQL执行的相关资料,文中通过实例代码和图文介绍的非常详细,对大家学习或者使用MyBatis具有一定的参考学习价值,需要的朋友可以参考下
    2023-01-01
  • Java实现代码块耗时测算工具类

    Java实现代码块耗时测算工具类

    这篇文章主要为大家介绍了如何利用Java语言编写一个工具类,用来测算代码块的耗时,同时还能显示进度,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-05-05
  • springboot+springmvc实现登录拦截

    springboot+springmvc实现登录拦截

    这篇文章主要介绍了springboot+springmvc实现登录拦截,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-10-10
  • Java简单实现SpringMVC+MyBatis分页插件

    Java简单实现SpringMVC+MyBatis分页插件

    自己最近搭建的一个SpringMVC+Mybatis的框架 属于无实体类的框架 并实现了Myabtis的自动分页和总数查询 只要传入分页参数便能自动查询总数和分页 总数封装在参数里面执行查询后可以直接从参数中获取
    2015-09-09
  • Java中的Spring Security配置过滤器

    Java中的Spring Security配置过滤器

    这篇文章主要介绍了Java中的Spring Security配置过滤器,文章通过围绕文章主题的相关资料展开详细内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-05-05
  • Java二叉树路径和代码示例

    Java二叉树路径和代码示例

    这篇文章主要介绍了Java二叉树路径和代码示例,具有一定借鉴价值,需要的朋友可以参考下。
    2017-12-12
  • 使用IDEA插件从数据库表生成实体类方式

    使用IDEA插件从数据库表生成实体类方式

    EasyCode是IntelliJ IDEA Ultimate版的代码生成插件,基于velocity模板,可以生成各种与数据有关的代码,如Entity、Dao、Service、Controller等,添加插件后,创建数据库连接,配置好信息并测试连接无误,即可通过表生成实体类
    2025-12-12
  • SpringBoot+Redission实现排行榜功能的示例代码

    SpringBoot+Redission实现排行榜功能的示例代码

    这篇文章主要介绍了基于SpringBoot+Redission实现排行榜功能,实现一个排行榜,要求按照分数和达成这个分数的时间排序,即相同分数下,时间早的在上面,文中通过代码示例介绍的非常详细,需要的朋友可以参考下
    2024-05-05

最新评论