`
greemranqq
  • 浏览: 977096 次
  • 性别: Icon_minigender_1
  • 来自: 重庆
社区版块
存档分类
最新评论

available 的理解和一些使用

阅读更多

一、序言

       这里主要介绍一下我们在读文件流,如何转换成byte[],从而引出这几种写法的一些原理和应用场景的区别。

 

二、测试代码

      2.1 我们先看代码,代码的作用是获得将文件流转换成byte 数组,我们暂时不管它的正确性,代码也精简了很多。

      

	// 这个用缓冲流
	public static byte[] getByte1(String name) throws IOException{
		FileInputStream is = null;
		is = new FileInputStream(new File(name));
		byte[] buff = new byte[1024*4];
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		int len = -1;
		while((len = is.read(buff)) != -1){
			baos.write(buff,0,len);
		}
		return baos.toByteArray();
	}
	
	// 这个用一次性读入
	public static byte[] getByte2(String name) throws IOException{
		InputStream is = null;
		is = new FileInputStream(new File(name));
		byte[] buff = new byte[is.available()];
		is.read(buff);
		return buff;
	}

 

     从上面代码看出,我们的区别是getByte1 拿到输入流对象了之后,再用输出流进行接收,然后再写到byte数组里面,而getByte2 是直接建立一个文件大小的byte 数组,一次性读入。从我的理解是:第二种方法的速度将优于第一种写法,其他方面我们稍后分析,先看看为什么优于第一种。

      首先,他们都用了FileInputStream 的read(byte[]) 方法,只是说每次读入字节数不一样,方法一是建立一个缓冲区的大小,方法二是一次全部读入,但是再看baos.write(buff,0,len); 的源码:

    

   
// 这是write 方法
public synchronized void write(byte b[], int off, int len) {
	if ((off < 0) || (off > b.length) || (len < 0) ||
            ((off + len) > b.length) || ((off + len) < 0)) {
	    throw new IndexOutOfBoundsException();
	} else if (len == 0) {
	    return;
	}
        // 我们可以看出,他其实是内部用了一个byte[] buf 进行存放我们缓存区的                   .   // 流数据数 ,长度不够了就会进行扩容,也就是数组的复制操作
        int newcount = count + len;
        if (newcount > buf.length) {
            // 这里我们可以看出,为什么最好用2的次方最好了,当我们的流没有填./满缓冲区的时             // 候, 会多余一部分空间,当然下面的代码还会处理那部分
            buf = Arrays.copyOf(buf, Math.max(buf.length << 1, newcount));
        }
        // 处理多余空间
        System.arraycopy(b, off, buf, count, len);
        count = newcount;
    }

  我们结合上面可以看出,如果文件稍微大一点,比如1G (小于JVM 内存限制),我们的缓冲区一般设置都是按MB 进行,那么会进行大量循环,大量数组的复制移位操作,而方法二,相当于一次就分配了1G空间,并且根据文件大小进行匹配的,每次分配跟准确,不会进行其他操作,速度会快一些。

 

三、那么为什么我们不一直采取第二种方式呢?

    先看看is.available() 的API

     

public int available()
              throws IOException返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数。下一个调用可能是同一个线程,也可能是另一个线程。一次读取或跳过此估计数个字节不会受阻塞,但读取或跳过的字节数可能小于该数。 
注意,有些 InputStream 的实现将返回流中的字节总数,但也有很多实现不会这样做。试图使用此方法的返回值分配缓冲区,以保存此流所有数据的做法是不正确的。 

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

类 InputStream 的 available 方法总是返回 0。 

此方法应该由子类重写。 
返回:
可以不受阻塞地从此输入流读取(或跳过)的估计字节数;如果到达输入流末尾,则返回 0。 

   

   在InputStream 里面,始终是返回0的,那么我们来看看FileInputStream 对该方法的重写:

    

// native 方法~。~
public native int available() throws IOException;
// 关于此方法在FileInputStream的实现,我们可以参考openjdk
// 或者 http://www.codeforge.cn/read/199045/io_FileInputStream.c__html 去下载
// - -很遗憾,在源码里面我没找到我想要的答案,我发了一个帖子:
// http://www.iteye.com/problems/100891
// 当然听群里朋友介绍,available 仅仅是返回不阻塞流里面的字节长度,和JDK描述一致。
// 也就是说只会获得流里面的长度,而不是文件长度。

    

     另外进过测试,FileInputStream available() 在获取流的可读字节数的时候,即使超过JVM限制,比如10G文件,也是可以获取大小的,也就是说要么是直接可以获取的文件大小的描述,而socket 是通过协议层进行规定,也能获取的。

 

   通常我们一般不能直接使用available方法的,因为上面提到available 读取的是不阻塞时流的长度。比如再网络传输时,我可能一个比较大的文件,当我打开一个流,如果这个流数据阻塞,还没传输过来,当你用该方法时,返回的总是0,或者说文件比较大,我分断传输,一段只能传输1G,那么你获得的大小只能该段流的大小,并不是文件的大小。

 

三、哪些地方可以使用available?

       1.在本地文件文件中,这里我一般是直接使用的,比如:

          

InputStream is = null;
is = new FileInputStream(new File(name));
byte[] buff = new byte[is.available()];
// 我的理解是本地文件获取的数值,应该是从文件描述里面获取的,也没啥阻塞,我个人认为可以直接// 使用.因为速度快,方便我们建立合适的缓存区

 

       2.网络中的文件

       a.比如web 中http 里面的文件流里面,第一种情况有content-length,那么小文件的情况,我们是直接可以通过request 获取该属性,也就知道文件的大小了,

       

       b.在某些情况下,比如文件比较大,采用采用分段方式,长连接的方式发送,不能一次知道文件大小,http 的header 里面就没有上面的content-length 属性,而是变成了Transfer-Encoding: chunked属性,这表示分段发送信息,但是对整个文件的接受,可以通过一些标志位,或者一些超时限制等方法处理,这里不具体研究了。

   

        c.socket 传输文件,这玩意我看了下源码,是没重写available方法的,也就是说我们不能通过这个知道流的字节数,一般情况下,我们可以先发送一段自定义的header 过去,描述文件大小,然后再循环持续获取流信息。

 

四、返回字节数组

        1.直接读入

          

// 这种方式上面已经提过
InputStream is = null;
is = new FileInputStream(new File(name));
byte[] buff = new byte[is.available()];
is.read(buff);

// 但是不排除因为某些原因,导致数据流没过来,在出现问题的情况下,可以利用阻
// 塞特性,先读入一个字节。
int len = is.read();
byte[] buff = new byte[is.available()+1];
buff[0] = (byte)len;
is.read(buff,1,buff.length);

 

   2.利用缓冲区

     

// 这个在某些地方需要利用输出流的时候
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int len = -1;
while((len = is.read(buff)) != -1){
	baos.write(buff,0,len);
        // 刷新一下,不然在缓冲区未满的时候不会写入
        baos.flush();
}
return baos.toByteArray();

 

   3.在一些网络中,比如要抓取网络流信息信息情况下

     

HttpURLConnection con = ....
con.connect();
InputStream in = (InputStream) con.getContent();
int total = ..// 获取总大小

byte buff[]  = new byte[1024*8]  // 缓冲区大小
int count = 0;
while(count < total){
     // 可以持续的对buff 进行复制,和上面byteOut.. 源码类似
     count += in.read(buff);
     // 里面可以加些超时限制,和一些自己的处理  
}

// 当然可以直接转换才Reader 处理

 

 

小结:

       1. 对于available的使用,群里有朋友是完全舍弃的,我的理解还是觉得存在即为合理,在某些地方使用上,还是能节约一些时间,可能我代码上有些偏执的追求吧。

       2,。上面大概解释了一些用法,不够全面,不对的地方请指点啦。

0
0
分享到:
评论

相关推荐

    解决docker报错There are no more lookback devices available

    在使用Docker的过程中,有时可能会遇到“`There are ...通过理解Loopback设备在Docker中的作用以及如何处理相关错误,你将能更有效地管理和维护你的Docker环境。记住,保持系统的整洁和合理配置是避免此类问题的关键。

    专业英语available一词多义PPT学习教案.pptx

    在会计学和其他专业领域,准确理解并运用"available"的多义性至关重要。 首先,"available"的基本含义是“可得到的”或“可用的”,表明某物处于可以被获取或使用的状态。例如,在"Those shoes are not available ...

    python material book available.rar

    在Web开发领域,Django和Flask是两个流行的Python Web框架,书中的材料可能包括它们的基本使用和高级特性,如路由、模板引擎、数据库集成等。 对于科学计算和数据分析,NumPy、SciPy和Matplotlib等库的使用方法是...

    前端开源库-grunt-available-tasks

    `grunt-available-tasks` 是一个专门针对 `Grunt.js` 构建的开源库,它旨在帮助开发者更清晰、更方便地管理和理解项目中的 Grunt 任务。本文将深入探讨 `Grunt.js` 和 `grunt-available-tasks`,并分享如何利用这些...

    TeX Commands available in MathJax.pdf

    文档中包含了一些TeX命令的示例和解释,以供用户使用和参考。Davide Cervone,MathJax的主要开发者,对文档进行了广泛的编辑和改进。 文档提到,它之所以庞大是因为它包含了大量的TeX命令,详细地展示了每一个命令...

    ATP详解--Available To Promise

    ATP,全称为Available To Promise,是供应链管理中一个关键的概念,主要用来确定企业能够向客户承诺交付的产品数量。在SAP系统中,ATP的实施涉及到一系列的配置和检查,确保准确无误地评估库存可用性。 首先,ATP的...

    Publically-Available-Large-Data-sets.zip_Big!

    9. 数据伦理:理解数据的来源和使用目的,避免数据滥用。 10. 数据可视化:有效的数据可视化工具和技术,如 Matplotlib、Seaborn 和 D3.js,可以帮助用户更好地理解和解释大数据。 掌握这些知识点,将使你具备处理...

    一种基于头部姿态分析注意力目标的概率推理模型_模态分析_available85w_注意力目标的概率推理_blockpu4_头部姿

    标题中的“一种基于头部姿态分析注意力目标的概率推理模型”揭示了该研究的核心,它涉及到计算机视觉、人工智能和机器学习领域的一些关键概念。首先,我们来深入理解这些关键词: 1. **头部姿态分析**:这是计算机...

    Scalable & Available Patterns for Success

    标题《Scalable & Available Patterns for Success》(可扩展性和高可用模式的成功之路)是由前Cloud Foundry内核架构师Derek Collison所撰写。该文档是一份117页的PPT,深入探讨了构建可扩展和高可用应用的关键成功...

    获取主机cpu使用率和内存使用率

    首先,我们要理解CPU使用率和内存使用率的概念。CPU使用率是指在一定时间内,处理器处于忙碌状态的百分比,反映了系统处理任务的能力。内存使用率则是指系统当前分配给进程使用的物理内存和虚拟内存的比例,体现了...

    lora_LoRa、server_railroadyts_lora_keptozo_available91h_

    标题中的“lora_LoRa、server_railroadyts_lora...通过深入理解LoRa协议、RailroadYTS系统以及keptozo和available91h的具体功能,我们可以更全面地掌握这个系统的运作方式,并利用这些知识来优化和扩展LoRa网络的应用。

    2020年高三英语开学大串讲阅读理解专题精讲20200427136

    同时,还会强调短语的使用,如"depend on"意为“依赖,依靠”,"in the fall"和"in the autumn"同义,表示“在秋天”,"require sb. to do sth."表示“要求某人做某事”。 课后,学生需要进行主题材料的关键词积累...

    grbl-coreXY-servo(available for ugs).zip

    《基于grbl-coreXY-servo的舵机版...同时,对舵机的使用和coreXY机械结构的理解,也有助于我们在更广泛的自动化和机器人项目中找到灵感。因此,无论是为了个人兴趣还是专业发展,深入研究这个项目都将带来丰厚的回报。

    The bevel control in Delphi is now available in VB.

    这包括了对控件的理解、使用,以及可能涉及的源码修改和系统集成。对于VB开发者来说,这是一次扩展其设计能力的机会,能够实现与Delphi类似的界面效果。同时,这也可能促进了不同编程语言之间技术的交流和融合。

    This wizard is not available because it requires a valid professional subscripti

    对于开发者来说,理解不同版本的IDE提供的功能至关重要,以便选择适合他们需求的版本。同时,学习如何有效地利用源代码生成工具可以提高生产力,这可能包括学习使用Maven插件、Gradle任务或其他自动化工具,它们可能...

    4480e0aa1cd1_目标检测_matlab运动检测_matlab运动目标_available6em_源码

    MATLAB是一种广泛使用的数学计算和编程环境,尤其在工程和科学研究领域。运动目标检测是计算机视觉和图像处理的一个关键任务,它涉及从连续的视频帧中识别和跟踪移动的物体。在安全监控、自动驾驶汽车、无人机等领域...

    高考英语阅读理解真题及解析答案,高考英语阅读理解词汇.doc

    这类题目的特点是考察学生对广告语言特点的理解和实际应用能力。广告英语通常具有强烈的说服力,用词独特且有时不规范,包括大量人名、地名、专有名词、缩略词以及祈使句和省略句。 【题型综述】广告类阅读理解主要...

    kb2577795,kb2553549 windows 2008 r2 补丁 解决No buffer space available

    首先,我们来理解一下socket套接字。在计算机网络编程中,socket是进程间通信的一种方式,特别是在不同主机之间进行数据传输时。它提供了一种标准接口,允许应用程序发送和接收数据,是TCP/IP协议栈的重要组成部分。...

    Spring集成Cxf暴露WebServices示例

    本示例将探讨如何通过Spring集成Cxf来暴露Web服务,帮助开发者更好地理解和实现这一功能。 首先,我们需要了解Spring与Cxf的基本概念。Spring框架提供了一个全面的编程和配置模型,用于简化企业级Java应用程序的...

    microftsoft available checklist

    包括如何避免单点故障、如何合理地管理不同级别的工作负载、如何理解并最小化服务依赖性、如何设计幂等性的任务和消息处理机制,以及如何选择和使用高可用性消息代理。这些措施共同构成了一个高可用性设计框架,能够...

Global site tag (gtag.js) - Google Analytics