java filterinputstream_java io FilterInputStream BufferedInputStream

1. FilterInputStream的结构图

5629e7ee9c20268855e200e79769bd07.png

/**

* A FilterInputStream contains some other input stream, which it

* uses as its basic source of data, possibly transforming the data along the

* way or providing additional functionality. The class

* FilterInputStream itself simply overrides all methods of

* InputStream with versions that pass all requests to the

* contained input stream. Subclasses of FilterInputStream may

* further override some of these methods and may also provide additional

* methods and fields.

*

*

@author

Jonathan Payne

*

@version

%I%, %G%

*

@since

JDK1.0

*/

public

class

FilterInputStream

extends

InputStream

FilterInputStream继承自InputStream, 可以将其他的输入流作为起数据源.

FilterInputStream只是简单的重写了InputStream里面的方法,直接看看BufferedInputStream

2. BufferedInputStream的类结构

/**

* A BufferedInputStream adds functionality to another input

* stream-namely, the ability to buffer the input and to support the

* mark and reset methods. When the

* BufferedInputStream is created, an internal buffer array is

* created. As bytes from the stream are read or skipped, the internal buffer is

* refilled as necessary from the contained input stream, many bytes at a time.

* The mark operation remembers a point in the input stream and the

* reset operation causes all the bytes read since the most recent

* mark operation to be reread before new bytes are taken from the

* contained input stream.

*

*/

public

class

BufferedInputStream

extends

FilterInputStream

BufferedInputStream为另外的输入流添加一些功能,其内部维护了一个缓冲区数组。

创建BufferedInputStream

private

static

int

defaultBufferSize

=

8192

;

protected

volatile

byte

buf[];

public

BufferedInputStream(InputStream in) {

this

(in, defaultBufferSize);

}

public

BufferedInputStream(InputStream in,

int

size) {

super

(in);

if

(size

<=

0

) {

throw

new

IllegalArgumentException(

"

Buffer size <= 0

"

);

}

buf

=

new

byte

[size];

}

初始化一个byte数组, 一次性从输入流中读取指定长度的的数据放到数组中。当程序要读取字节的时候,

直接从byte数组里面读取。

3. BufferedInputStream的缓冲区

通过上面的构造函数可以看到byte数组具有缓冲区的功能, 每次读去数据都是从该缓冲区数组里面读取。

protected

int

count;

//

当前缓冲区内总共有多少有效数据

protected

int

pos;

//

表示当前读取到的位置,即byte数组的当前下标,下次读取从该位置读取

protected

int

markpos

=

-

1

;

//

标记的位置

protected

int

marklimit;

//

最多能mark的字节长度,也就是从mark位置到当前pos的最大长度

public

synchronized

int

read()

throws

IOException {

if

(pos

>=

count) {

fill();

if

(pos

>=

count)

return

-

1

;

}

return

getBufIfOpen()[pos

++

]

&

0xff

;

}

通过read方法可以看到,当缓冲区的数据全部读完的时候, 填充缓冲区。这样读取数据都是从缓冲区里面

读取,不会从真正的数据源读取。

3.1 read()方法 返回值 getBufIfOpen()[pos++] & 0xff

我们知道当文件到达结尾的时候是以  -1 表示, 如果是字符流没有负数,返回-1是OK的。但是byte或int 本身包含 –1 这个数, 所以不能直接返回 –1 。

在java中, byte的大小是8 bits 而 int的大小是 32bits;java的二进制采用的是补码的形式

0xff是int类型,二进制为0000 0000 0000 0000 0000 0000 1111 1111

上述的与运算实际上读取的byte先被强制转换成了int,例如byte的-1(最高位表示符号位,以补码的形式表示负数为:1111 1111)

转换为int之后的二进制1111 1111 1111 1111 1111 1111 1111 1111

& 0xff之后高位去0,  最后返回的结果是0000 0000 0000 0000 0000 0000 1111 1111, 为int值为256 .

其-128~-1被转为int中128~256的正数表示。这样解决了可以用-1表示文件已经读完。

但关键是数据的值发生了变化,真正要用读取的数据时是否还能拿到原始的byte。

还拿上面那个例子来看,当读取返回一个256时,将其强制类型转换为byte,(byte)256得到byte的-1,

因为byte只有8位,当int的高位被丢弃后就只剩下1111 1111,在byte中高位的1表示符号位为负数,最终的结果即是byte的-1;

同样byte的-128(1000 0000)被转为int的128(0000 0000 0000 0000 0000 0000 1000 0000),强制类型转换后还原byte的1000 0000。

关于源码补码可以参考 :

http://blog.csdn.net/js_gary/article/details/6715636

3.2 线程安全

我们知道 ++操作其实是线程不安全的, BufferedInputStream里面的public方法都是synchronized的,已保证整个缓存数组是

线程安全的, 关闭方法没有加synchronized,是为了避免过大的系统消耗。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值