BufferedInputStream 介绍
BufferedInputStream 介绍 BufferedInputStream 是缓冲输入流。它继承于FilterInputStream。 BufferedInputStream 函数列表 ? 说明: 要想读懂BufferedInputStream的源码,就要先理解它的思想。BufferedInputStream的作用是为其它输入流提供缓冲功能。创建BufferedInputStream时,我们会通过它的构造函数指定某个输入流为参数。BufferedInputStream会将该输入流数据分批读取,每次读取一部分到缓冲中;操作完缓冲中的这部分数据之后,再从输入流中读取下一部分的数据。 下面,我就BufferedInputStream中最重要的函数fill()进行说明。其它的函数很容易理解,我就不详细介绍了,大家可以参考源码中的注释进行理解。 fill() 源码如下: ? 根据fill()中的if...else...,下面我们将fill分为5种情况进行说明。 ?情况1:读取完buffer中的数据,并且buffer没有被标记 执行流程如下, 说明: 这种情况发生的情况是 — — 输入流中有很长的数据,我们每次从中读取一部分数据到buffer中进行操作。每次当我们读取完buffer中的数据之后,并且此时输入流没有被标记;那么,就接着从输入流中读取下一部分的数据到buffer中。 理解这个思想之后,我们再对这种情况下的fill()的代码进行分析,就特别容易理解了。 ?情况2:读取完buffer中的数据,buffer的标记位置>0,并且buffer中没有多余的空间 执行流程如下, 为了方便分析,我们将这种情况下fill()执行的操作等价于以下代码? private void fill() throws IOException { byte[] buffer = getBufIfOpen(); if (markpos >= 0 && pos >= buffer.length) { if (markpos > 0) { int sz = pos - markpos; System.arraycopy(buffer,sz); pos = sz; markpos = 0; } } count = pos; int n = getInIfOpen().read(buffer,buffer.length - pos); if (n > 0) count = n + pos; } ? 说明: 这种情况发生的情况是 — — 输入流中有很长的数据,我们每次从中读取一部分数据到buffer中进行操作。当我们读取完buffer中的数据之后,并且此时输入流存在标记时;那么,就发生情况2。此时,我们要保留“被标记位置”到“buffer末尾”的数据,然后再从输入流中读取下一部分的数据到buffer中。 理解这个思想之后,我们再对这种情况下的fill()代码进行分析,就特别容易理解了。 注意:执行过情况2之后,markpos的值由“大于0”变成了“等于0”! 情况3:读取完buffer中的数据,buffer被标记位置=0,buffer中没有多余的空间,并且buffer.length>=marklimit 执行流程如下, 为了方便分析,我们将这种情况下fill()执行的操作等价于以下代码:?
?
?
private void fill() throws IOException { byte[] buffer = getBufIfOpen(); if (markpos >= 0 && pos >= buffer.length) { if ( (markpos <= 0) && (buffer.length >= marklimit) ) { markpos = -1; /* buffer got too big,invalidate mark */ pos = 0; /* drop buffer contents */ } } count = pos; int n = getInIfOpen().read(buffer,buffer.length - pos); if (n > 0) count = n + pos; } ? 说明:这种情况的处理非常简单。首先,就是“取消标记”,即 markpos = -1;然后,设置初始化位置为0,即pos=0;最后,再从输入流中读取下一部分数据到buffer中。 情况4:读取完buffer中的数据,buffer被标记位置=0,buffer中没有多余的空间,并且buffer.length<marklimit 执行流程如下, 为了方便分析,我们将这种情况下fill()执行的操作等价于以下代码: 说明: 这种情况的处理非常简单。 (02) 接着,将buffer中的数据拷贝到新数组nbuf中。通过System.arraycopy(buffer,pos) 假设,marklimit是无限大的,而且我们设置了markpos。当我们从输入流中每读完一部分数据并读取下一部分数据时,都需要保存markpos所标记的数据;这就意味着,我们需要不断执行情况4中的操作,要将buffer的容量扩大……随着读取次数的增多,buffer会越来越大;这会导致我们占据的内存越来越大。所以,我们需要给出一个marklimit;当buffer>=marklimit时,就不再保存markpos的值了。 情况5:除了上面4种情况之外的情况 执行流程如下, 为了方便分析,我们将这种情况下fill()执行的操作等价于以下代码: ? private void fill() throws IOException { byte[] buffer = getBufIfOpen(); count = pos; int n = getInIfOpen().read(buffer,buffer.length - pos); if (n > 0) count = n + pos; } ? 说明:这种情况的处理非常简单。直接从输入流读取部分新数据到buffer中。 示例代码 关于BufferedInputStream中API的详细用法,参考示例代码(BufferedInputStreamTest.java): 程序中读取的bufferedinputstream.txt的内容如下: abcdefghijklmnopqrstuvwxyz 运行结果: 0 : 0x61 ? ? 原文链接:https://www.aspzz.cn/article/113801.htm (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |