了解下JAVA的java io进修(十一) 缓冲输出流的认知、源码和示例
在ruby里才是一切皆对象。当然我不并不是很了解ruby,但是ruby确实是将语法简化得很好。BufferedInputStream(缓冲输出流)的认知、源码和示例
本章内容包含3个部分:BufferedInputStream先容,BufferedInputStream源码,和BufferedInputStream利用示例。
BufferedInputStream先容
BufferedInputStream是缓冲输出流。它承继于FilterInputStream。
BufferedInputStream的感化是为另外一个输出流增加一些功效,比方,供应“缓冲功效”和撑持“mark()标志”和“reset()重置办法”。
BufferedInputStream实质上是经由过程一个外部缓冲区数组完成的。比方,在新建某输出流对应的BufferedInputStream后,当我们经由过程read()读取输出流的数据时,BufferedInputStream会将该输出流的数据分批的填进到缓冲区中。每当缓冲区中的数据被读完以后,输出流会再次添补数据缓冲区;云云重复,直到我们读完输出流数据地位。
BufferedInputStream函数列表
BufferedInputStream(InputStreamin)
BufferedInputStream(InputStreamin,intsize)
synchronizedintavailable()
voidclose()
synchronizedvoidmark(intreadlimit)
booleanmarkSupported()
synchronizedintread()
synchronizedintread(byte[]buffer,intoffset,intbyteCount)
synchronizedvoidreset()
synchronizedlongskip(longbyteCount)BufferedInputStream源码剖析(基于jdk1.7.40)
packagejava.io;
importjava.util.concurrent.atomic.AtomicReferenceFieldUpdater;
publicclassBufferedInputStreamextendsFilterInputStream{
//默许的缓冲巨细是8192字节
//BufferedInputStream会依据“缓冲区巨细”来逐次的添补缓冲区;
//即,BufferedInputStream添补缓冲区,用户读取缓冲区,读完以后,BufferedInputStream会再次添补缓冲区。云云轮回,直到读完数据...
privatestaticintdefaultBufferSize=8192;
//缓冲数组
protectedvolatilebytebuf[];
//缓存数组的原子更新器。
//该成员变量与buf数组的volatile关头字配合构成了buf数组的原子更新功效完成,
//即,在多线程中操纵BufferedInputStream对象时,buf和bufUpdater都具有原子性(分歧的线程会见到的数据都是不异的)
privatestaticfinal
AtomicReferenceFieldUpdater<BufferedInputStream,byte[]>bufUpdater=
AtomicReferenceFieldUpdater.newUpdater
(BufferedInputStream.class,byte[].class,"buf");
//以后缓冲区的无效字节数。
//注重,这里是指缓冲区的无效字节数,而不是输出流中的无效字节数。
protectedintcount;
//以后缓冲区的地位索引
//注重,这里是指缓冲区的地位索引,而不是输出流中的地位索引。
protectedintpos;
//以后缓冲区的标志地位
//markpos和reset()共同利用才成心义。操纵步骤:
//(01)经由过程mark()函数,保留pos的值到markpos中。
//(02)经由过程reset()函数,会将pos的值重置为markpos。接着经由过程read()读取数据时,就会从mark()保留的地位入手下手读取。
protectedintmarkpos=-1;
//marklimit是标志的最年夜值。
//检察本栏目更多出色内容:http://www.bianceng.cn/Programming/Java/
//关于marklimit的道理,我们在前面的fill()函数剖析中会具体申明。这对了解BufferedInputStream相称主要。
protectedintmarklimit;
//猎取输出流
privateInputStreamgetInIfOpen()throwsIOException{
InputStreaminput=in;
if(input==null)
thrownewIOException("Streamclosed");
returninput;
}
//猎取缓冲
privatebyte[]getBufIfOpen()throwsIOException{
byte[]buffer=buf;
if(buffer==null)
thrownewIOException("Streamclosed");
returnbuffer;
}
//机关函数:新建一个缓冲区巨细为8192的BufferedInputStream
publicBufferedInputStream(InputStreamin){
this(in,defaultBufferSize);
}
//机关函数:新建指定缓冲区巨细的BufferedInputStream
publicBufferedInputStream(InputStreamin,intsize){
super(in);
if(size<=0){
thrownewIllegalArgumentException("Buffersize<=0");
}
buf=newbyte;
}
//从“输出流”中读取数据,并添补到缓冲区中。
//前面会对该函数举行具体申明!
privatevoidfill()throwsIOException{
byte[]buffer=getBufIfOpen();
if(markpos<0)
pos=0;/*nomark:throwawaythebuffer*/
elseif(pos>=buffer.length)/*noroomleftinbuffer*/
if(markpos>0){/*canthrowawayearlypartofthebuffer*/
intsz=pos-markpos;
System.arraycopy(buffer,markpos,buffer,0,sz);
pos=sz;
markpos=0;
}elseif(buffer.length>=marklimit){
markpos=-1;/*buffergottoobig,invalidatemark*/
pos=0;/*dropbuffercontents*/
}else{/*growbuffer*/
intnsz=pos*2;
if(nsz>marklimit)
nsz=marklimit;
bytenbuf[]=newbyte;
System.arraycopy(buffer,0,nbuf,0,pos);
if(!bufUpdater.compareAndSet(this,buffer,nbuf)){
thrownewIOException("Streamclosed");
}
buffer=nbuf;
}
count=pos;
intn=getInIfOpen().read(buffer,pos,buffer.length-pos);
if(n>0)
count=n+pos;
}
//读取下一个字节
publicsynchronizedintread()throwsIOException{
//若已读完缓冲区中的数据,则挪用fill()从输出流读取下一部分数据来添补缓冲区
if(pos>=count){
fill();
if(pos>=count)
return-1;
}
//从缓冲区中读取指定的字节
returngetBufIfOpen()&0xff;
}
//将缓冲区中的数据写进到字节数组b中。off是字节数组b的肇端地位,len是写进长度
privateintread1(byte[]b,intoff,intlen)throwsIOException{
intavail=count-pos;
if(avail<=0){
//减速机制。
//假如读取的长度年夜于缓冲区的长度而且没有markpos,
//则间接从原始输出流中举行读取,从而制止无谓的COPY(从原始输出流至缓冲区,读取缓冲区全体数据,清空缓冲区,
//从头填进原始输出流数据)
if(len>=getBufIfOpen().length&&markpos<0){
returngetInIfOpen().read(b,off,len);
}
//若已读完缓冲区中的数据,则挪用fill()从输出流读取下一部分数据来添补缓冲区
fill();
avail=count-pos;
if(avail<=0)return-1;
}
intcnt=(avail<len)?avail:len;
System.arraycopy(getBufIfOpen(),pos,b,off,cnt);
pos+=cnt;
returncnt;
}
//将缓冲区中的数据写进到字节数组b中。off是字节数组b的肇端地位,len是写进长度
publicsynchronizedintread(byteb[],intoff,intlen)
throwsIOException
{
getBufIfOpen();//Checkforclosedstream
if((off|len|(off+len)|(b.length-(off+len)))<0){
thrownewIndexOutOfBoundsException();
}elseif(len==0){
return0;
}
//读取到指定长度的数据才前往
intn=0;
for(;;){
intnread=read1(b,off+n,len-n);
if(nread<=0)
return(n==0)?nread:n;
n+=nread;
if(n>=len)
returnn;
//ifnotclosedbutnobytesavailable,return
InputStreaminput=in;
if(input!=null&&input.available()<=0)
returnn;
}
}
//疏忽n个字节
publicsynchronizedlongskip(longn)throwsIOException{
getBufIfOpen();//Checkforclosedstream
if(n<=0){
return0;
}
longavail=count-pos;
if(avail<=0){
//Ifnomarkpositionsetthendontkeepinbuffer
if(markpos<0)
returngetInIfOpen().skip(n);
//Fillinbuffertosavebytesforreset
fill();
avail=count-pos;
if(avail<=0)
return0;
}
longskipped=(avail<n)?avail:n;
pos+=skipped;
returnskipped;
}
//下一个字节是不是存可读
publicsynchronizedintavailable()throwsIOException{
intn=count-pos;
intavail=getInIfOpen().available();
returnn>(Integer.MAX_VALUE-avail)
?Integer.MAX_VALUE
:n+avail;
}
//标志“缓冲区”中以后地位。
//readlimit是marklimit,关于marklimit的感化,参考前面的申明。
publicsynchronizedvoidmark(intreadlimit){
marklimit=readlimit;
markpos=pos;
}
//将“缓冲区”中以后地位重置到mark()所标志的地位
publicsynchronizedvoidreset()throwsIOException{
getBufIfOpen();//Causeexceptionifclosed
if(markpos<0)
thrownewIOException("Resettingtoinvalidmark");
pos=markpos;
}
publicbooleanmarkSupported(){
returntrue;
}
//封闭输出流
publicvoidclose()throwsIOException{
byte[]buffer;
while((buffer=buf)!=null){
if(bufUpdater.compareAndSet(this,buffer,null)){
InputStreaminput=in;
in=null;
if(input!=null)
input.close();
return;
}
//ElseretryincaseanewbufwasCASedinfill()
}
}
}<p>
C#是盗用了Java的源代码,仿照开发的,原因是Java是开源的啊,盗了也白盗,还有一点,开发C#语言的团队是就是开发Java语言的团队,是微软重金挖过去的啊 Java 不同于一般的编译执行计算机语言和解释执行计算机语言。它首先将源代码编译成二进制字节码(bytecode),然后依赖各种不同平台上的虚拟机来解释执行字节码。从而实现了“一次编译、到处执行”的跨平台特性。 是一种突破用户端机器环境和CPU 象、泛型编程的特性,广泛应用于企业级Web应用开发和移动应用开发。 让你能够真正掌握接口或抽象类的应用,从而在原来的Java语言基础上跃进一步,更重要的是,设计模式反复向你强调一个宗旨:要让你的程序尽可能的可重用。 你就该学一学Servlet了。Servlet就是服务器端小程序,他负责生成发送给客户端的HTML文件。JSP在执行时,也是先转换成Servlet再运行的。虽说JSP理论上可以完全取代Servlet,这也是SUN推出JSP的本意,可是Servlet用来控制流程跳转还是挺方便的,也令程序更清晰。接下来你应该学习一下Javabean了,可能你早就看不管JSP在HTML中嵌Java代码的混乱方式了,这种方式跟ASP又有什么区别呢? J2SE开发桌面应用软件比起 VC,VB,DEPHI这些传统开发语言来说,优势好象并不明显。J2ME对于初学者来说,好象又有点深奥,而且一般开发者很难有开发环境。 《JAVA语言程序设计》或《JAVA从入门到精通》这两本书开始学,等你编程有感觉的时候也可以回看一下。《JAVA读书笔记》这本书,因为讲的代码很多,也很容易看懂,涉及到面也到位。是你学习技术巩固的好书,学完后就看看《JAVA编程思想》这本书,找找一个自己写的代码跟书上的代码有什么不一样。
页:
[1]