文档章节

java io FilterInputStream BufferedInputStream

牛哥哥
 牛哥哥
发布于 2012/08/11 17:05
字数 1039
阅读 294
收藏 0

1. FilterInputStream的结构图

image


   
/** * 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,是为了避免过大的系统消耗。

© 著作权归作者所有

共有 人打赏支持
牛哥哥
粉丝 2
博文 8
码字总数 1984
作品 0
大渡口
高级程序员
JAVA NIO之浅谈内存映射文件原理与DirectMemory

JAVA类库中的NIO包相对于IO 包来说有一个新功能是内存映射文件,日常编程中并不是经常用到,但是在处理大文件时是比较理想的提高效率的手段。本文我主要想结合操作系统中(OS)相关方面的知识...

pczhangtl
2013/11/19
0
0
The Go Type System

Recently I've become very interested inthe Golang programming language. Golang, or Google Go as it's often called, is a new programming language designed by some fairly well-kno......

Jerikc
2014/08/30
0
0
探究java.io之I/O类和接口

基于流的I/O系统被打包到java.io包中,本系列介绍那些自Java最初发布以来就已提供且广泛使用的部分。然而,从1.4版本开始,Java添加了另一套I/O系统,被称为NIO(也就是new I/O系统的缩写)。...

柳哥
2014/11/10
0
0
详细介绍Java语言中的IO系统

Java的核心库java.io提供了全面的IO接口,包括:文件读写,标准设备输出等等。Java中IO是以流为基础进行输入输出的,所有数据被串行化写入输出流,或者从输入流读入。在具体使用中很多初学者...

风一样
2011/08/03
0
0
(十)装饰器模式详解(与IO不解的情缘)

LZ到目前已经写了九个设计模式,回过去看看,貌似写的有点凌乱,LZ后面会尽量改进。 那么本章LZ和各位读友讨论一个与JAVA中IO有着不解情缘的设计模式,装饰器模式。 定义:装饰模式是在不必改...

Sheamus
2015/02/02
0
0

没有更多内容

加载失败,请刷新页面

加载更多

arts-week10

Algorithm 905. Sort Array By Parity - LeetCode Review Who’s Afraid of the Big Bad Preloader? 一文读懂前端缓存 一个网络请求3个步骤:请求,处理,响应,而前端缓存主要在请求处响应这两步...

yysue
今天
0
0
00.编译OpenJDK-8u40的整个过程

前言 历经2天的折腾总算把OpenJDK给编译成功了,要说为啥搞这个,还得从面试说起,最近出去面试经常被问到JVM的相关东西,总感觉自己以前学的太浅薄,所以回来就打算深入学习,目标把《深入理...

凌晨一点
今天
5
0
python: 一些关于元组的碎碎念

初始化元组的时候,尤其是元组里面只有一个元素的时候,会出现一些很蛋疼的情况: def checkContentAndType(obj): print(obj) print(type(obj))if __name__=="__main__": tu...

Oh_really
昨天
6
2
jvm crash分析工具

介绍一款非常好用的jvm crash分析工具,当jvm挂掉时,会产生hs_err_pid.log。里面记录了jvm当时的运行状态以及错误信息,但是内容量比较庞大,不好分析。所以我们要借助工具来帮我们。 Cras...

xpbob
昨天
128
0
Qt编写自定义控件属性设计器

以前做.NET开发中,.NET直接就集成了属性设计器,VS不愧是宇宙第一IDE,你能够想到的都给你封装好了,用起来不要太爽!因为项目需要自从全面转Qt开发已经6年有余,在工业控制领域,有一些应用...

飞扬青云
昨天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部