下载

1下载券

加入VIP
  • 专属下载特权
  • 现金文档折扣购买
  • VIP免费专区
  • 千万文档免费下载

上传资料

关闭

关闭

关闭

封号提示

内容

首页 Java_IO完全总结

Java_IO完全总结.pdf

Java_IO完全总结

天天xIgU_994
2011-12-02 0人阅读 举报 0 0 暂无简介

简介:本文档为《Java_IO完全总结pdf》,可适用于IT/计算机领域

JavaJavaJavaJavaIOIOIOIO完全总结本篇主要讲述IO相关的内容主要包括:与IO相关的简单的历史背景知识JavaIO的简单分类与IO设计相关的两个模式同时列举几个简单的例子分析其中几个实现的源代码最后给大家一些简单扩展的例子。治学先治史下面我们先从简单的历史开始吧!一、历史背景“对语言设计人员来说创建好的输入/输出系统是一项特别困难的任务。”――《ThinkinJava》无论是系统、还是语言的设计中IO的设计都是异常复杂的。面临的最大的挑战一般是如何覆盖所有可能的因素我们不仅仅要考虑文件、控制台、网络、内存等不同的种类而且要处理大量的不同的读取方式如:顺序读取、随机读取二进制读取、字符读取按行读取、按字符读取……Linux是第一个将设备抽象为文件的操作系统在Linux中所有的外部设备都可以用读取文件的方法读取这样编程人员就可以以操作文件的方法操作任何设备。C在IO方面也做了一些改进――引进了流的概念我们可以通过cin、cout读写一些对象。Java语言在IO设计方面取得较大的成功它是完全面向对象的主要采用装饰器模式避免大量的类包括了最大的可能性提供了较好的扩展机制……“Java库的设计者通过创建大量类来攻克这个难题。事实上Java的IO系统采用了如此多的类以致刚开始会产生不知从何处入手的感觉(具有讽刺意味的是Java的IO设计初衷实际要求避免过多的类)。”上面一段来自《ThinkinJava》确实很多初学者刚刚学习java的IO时会比较茫然不过等我们知道装饰器模式(Decorator)的用意、场景及其在Java的IO包中的使用你可能会真正领会整个IO的FrameWork。二、IOIOIOIO的分类JavaIO一般包含两个部分:javaio包中堵塞型IOjavanio包中的非堵塞型IO通常称为NewIO。学过操作系统的朋友都知道系统运行的瓶颈一般在于IO操作一般打开某个IO通道需要大量的时间同时端口中不一定就有足够的数据这样read方法就一直等待读取此端口的内容从而浪费大量的系统资源。有人也许会提出使用java的多线程技术啊!但是在当前进程中创建线程也是要花费一定的时间和系统资源的因此不一定可取。JavaNewIO的非堵塞技术主要采用了Observer模式就是有一个具体的观察者和=监测IO端口如果有数据进入就会立即通知相应的应用程序。这样我们就避免建立多个线程同时也避免了read等待的时间。不过本篇主要讲述java的堵塞型IO就是我们通常应用的那个包。打开你的javaio包你可以看到Java的IO包含大量的类和接口(JDK中包含个类或者接口)如此众多的类和接口似乎无从下手。下面就将IO简单地分类。Java的IO主要包含三个部分:流式部分――IO的主体部分非流式部分――主要包含一些辅助流式部分的类如:File类、RandomAccessFile类和FileDescriptor等类文件读取部分的与安全相关的类如:SerializablePermission类。以及与本地操作系统相关的文件系统的类如:FileSystem类和WinFileSystem类和WinNTFileSystem类。流式部分可以概括为:两个对应一个桥梁。两个对应指:字节流(ByteStream)和字符流(CharStream)的对应输入和输出的对应。一个桥梁指:从字节流到字符流的桥梁。对应于输入和输出为InputStreamReader和OutputStreamWriter。在流的具体类中又可以具体分为:介质流(MediaStream或者称为原始流RawStream)――主要指一些基本的流他们主要是从具体的介质上如:文件、内存缓冲区(Byte数组、Char数组、StringBuffer对象)等读取数据过滤流(FilterStream)――主要指所有FilterInputStreamFilterOutputStream和FilterReaderFilterWriter的子类主要是对其包装的类进行某些特定的处理如:缓存等。三、IOIOIOIO中的流流具有最基本的特点:“Onedimension,onedirection”即流是一维的同时流是单向的。关于维和我们通常说的一维长度二维平面三维空间四维时空……是同一个概念流就是一维的。单向就是只可以一个方向(按顺序从头至尾依次)读取不可以读到某个位置再返回前面某个位置。流的概念和实际水流的概念基本一致水只可以从高向低一个方向流动。我们某时在目地喝了一口水下次在同一个地点喝水已经不是当时的那片水了。流的这种特性在JMS(JavaMessageService)的API设计中得到了体现。JMS是JEE平台下面向消息中间件的一个标准。(关于中间件技术有机会和大家探讨)JMS中有五种具体类型的消息这些消息一般分为两类:流式的消息――包含ByteMessage和StreamMessage非流式的消息――包含TextMessage、ObjectMessage和MapMessage。我们在明白IO中流的特点后基本可以明白JMSAPI设计者的意图。可能有些场合我们需要在文件中随机插入数据、在流中来来回回地执行某些操作这时候我们绝对不可以使用流相关的对象。很幸运JDK的设计者为我们设计了一个单独的类RandomAccessFile它可以完成打开、关闭文件、以基本数据类型的方式读取数据、读取下一个行、以等格式读取数据、写入各种类型的数据、比较特殊的是他可以通过文件指针的seek方法让文件指针移到某个位置可以通过getFilePointer方法得到当前指针的位置、可以通过length()方法得到当前文件的容量、通过getFD得到FileDescriptor对象通过getChannel方法得到FileChannel对象从而和NewIO整合。()()()下面比较简单的分析IO中的各个对象吧!IOIOIOIO中的输入字节流下面是IO中输入字节流的继承图。oInputStreamInputStreamInputStreamInputStreamoByteArrayInputStreamByteArrayInputStreamByteArrayInputStreamByteArrayInputStreamoFileInputStreamFileInputStreamFileInputStreamFileInputStreamoFilterInputStreamFilterInputStreamFilterInputStreamFilterInputStreamoBufferedInputStreamBufferedInputStreamBufferedInputStreamBufferedInputStreamoDataInputStreamDataInputStreamDataInputStreamDataInputStreamoLineNumberInputStreamLineNumberInputStreamLineNumberInputStreamLineNumberInputStreamoPushbackInputStreamPushbackInputStreamPushbackInputStreamPushbackInputStreamoObjectInputStreamObjectInputStreamObjectInputStreamObjectInputStreamoPipedInputStreamPipedInputStreamPipedInputStreamPipedInputStreamoSequenceInputStreamSequenceInputStreamSequenceInputStreamSequenceInputStreamoStringBufferInputStreamStringBufferInputStreamStringBufferInputStreamStringBufferInputStream在上面的关系图中可以看出:InputStream是所有的输入字节流的父类它是一个抽象类。ByteArrayInputStream、StringBufferInputStream、FileInputStream是三种基本的介质流它们分别将Byte数组、StringBuffer、和本地文件中读取数据。PipedInputStream是从与其它线程共用的管道中读取数据与Piped相关的知识会用专门的一小节讲解。ObjectInputStream和所有FilterInputStream的子类都是装饰流(装饰器模式的主角)。下表列出了这些流的功能及如何使用它们(具体使用在讲解完装饰器模式后会举几个例子)。基本输入字节流:类功能如何构造怎样使用ByteArrayInputStream将内存中的Byte数组适配为一个InputStream。从内存中的Byte数组创建该对象(种方法)一般作为数据源会使用其它装饰流提供额外的功能一般都建议加个缓冲功能。StringBufferInputStream将内存中的字符串适配为一个InputStream。从一个String对象创建该对象。底层的实现使用StringBuffer。该类被Deprecated。主要原因是StringBuffer不应该属于字节流所以推荐使用StringReader。一般作为数据源同样会使用其它装饰器提供额外的功能。FileInputStream最基本的文件输入流。主要用于从文件中读取信息。通过一个代表文件路径的String、File对象或者FileDescriptor对象创建。一般作为数据源同样会使用其它装饰器提供额外的功能。PipedInputStream读取从对应PipedOutputStream写入的数据。在流中实现了管道的概念。利用对应的PipedOutputStream创建。在多线程程序中作为数据源同样会使用其它装饰器提供额外的功能。SequenceInputStream将个或者多个InputStream对象转变为一个InputStream使用两个InputStream或者内部对象为InputStream的Enumeration对象创建该对象。一般作为数据源同样会使用其它装饰器提供额外的功能。FilterInputStream给其它被装饰对象提供额外功能的抽象类主要子类见下表装饰、输入字节流:类功能如何构造怎样使用DataInputStream一般和DataOutputStream配对使用,完成基本数据类型的读写。利用一个InputStream构造。提供了大量的读取基本数据类新的读取方法。BufferedInputStream使用该对象阻止每次读取一个字节都会频繁操作IO。将字节读取一个缓存区从缓存区读取。利用一个InputStream、或者带上一个自定义的缓存区的大小构造。使用InputStream的方法读取只是背后多一个缓存的功能。设计模式中透明装饰器的应用。LineNumberInputStream跟踪输入流中的行号。可利用一个InputStream构以调用getLineNumber()和setLineNumber(int)方法得到和设置行号。造。紧紧增加一个行号。可以象使用其它InputStream一样使用。PushbackInputStream可以在读取最后一个byte后将其放回到缓存中。利用一个InputStream构造。一般仅仅会在设计compiler的scanner时会用到这个类。在我们的java语言的编译器中使用它。很多程序员可能一辈子都不需要。IOIOIOIO中的输出字节流下面是IO中输出字节流的继承图。•OutputStream•ByteArrayOutputStreamFileOutputStreamFilterOutputStream•BufferedOutputStreamDataOutputStreamPrintStreamObjectOutputStreamPipedOutputStream在上面的关系图中可以看出:OutputStream是所有的输出字节流的父类它是一个抽象类。ByteArrayOutputStream、FileOutputStream是两种基本的介质流它们分别向Byte数组、和本地文件中写入数据。PipedOutputStream是向与其它线程共用的管道中写入数据ObjectOutputStream和所有FilterOutputStream的子类都是装饰流。下表列出了输出字节流的功能及如何使用它们。类功能如何构造怎样使用ByteArrayOutputStream在内存中创建一个buffer。所有写入此流中的数据都被放入到此buffer中。无参或者使用一个可选的初始化buffer的大小的参数构造。一般将其和FilterOutputStream套接得到额外的功能。建议首先和BufferedOutputStream套接实现缓冲功能。通过toByteArray方法可以得到流中的数据。(不通明装饰器的用法)FileOutputStream将信息写入文件中。使用代表文件路径的String、File对象或者FileDescriptor对象创建。还可以加一个代表写入的方式是否为append的标记。一般将其和FilterOutputStream套接得到额外的功能。PipedOutputStream任何写入此对象的信息都被放入对应PipedInputStream对象的缓存中从而完成线程的通信实现了“管道”的概念。具体在后面详细讲解。利用PipedInputStream构造在多线程程序中数据的目的地的。一般将其和FilterOutputStream套接得到额外的功能。FilterOutputStream实现装饰器功能的抽象类。见下表为其它OutputStream对象增加额外的功能。见下表装饰输出字节流:类功能如何构造怎样使用DataOutputStream通常和DataInputStream配合使用使用它可以写入基本数据类新。使用OutputStream构造包含大量的写入基本数据类型的方法。PrintStream产生具有格式的输出信息。(一般地在java程序中DataOutputStream用于数据的存储即JEE中持久层完成的功能PrintStream完成显示的功能类似于JEE中表现层的功能)使用OutputStream和一个可选的表示缓存是否在每次换行时是否flush的标记构造。还提供很多和文件相关的构造方法。一般是一个终极(“final”)的包装器很多时候我们都使用它!BufferedOutputStream使用它可以避免频繁地向IO写入数据数据一般都写入一个缓存区在调用flush方法后会清空缓存、一次完成数据的写入。从一个OutputStream或者和一个代表缓存区大小的可选参数构造。提供和其它OutputStream一致的接口只是内部提供一个缓存的功能。字节流的输入与输出的对应在节讲过输入与输出的对应下图表示字节流部分的输入与输出的对应关系。上图中蓝色的为主要的对应部分红色的部分就是不对应部分。我习惯上称之为“不入流”部分。紫色的虚线部分代表这些流一般要搭配使用。从上面的图中可以看出JavaIO中的字节流是极其对称的。“存在及合理”我们看看这些字节流中不太对称的几个类吧!LineNumberInputStream主要完成从流中读取数据时会得到相应的行号至于什么时候分行、在哪里分行是由改类主动确定的并不是在原始中有这样一个行号。在输出部分没有对应的部分我们完全可以自己建立一个LineNumberOutputStream在最初写入时会有一个基准的行号以后每次遇到换行时会在下一行添加一个行号看起来也是可以的。好像更不入流了。PushbackInputStream的功能是查看最后一个字节不满意就放入缓冲区。主要用在编译器的语法、词法分析部分。输出部分的BufferedOutputStream几乎实现相近的功能。StringBufferInputStream已经被Deprecated本身就不应该出现在InputStream部分主要因为String应该属于字符流的范围。已经被废弃了当然输出部分也没有必要需要它了!还允许它存在只是为了保持版本的向下兼容而已。SequenceInputStream可以认为是一个工具类将两个或者多个输入流当成一个输入流依次读取。完全可以从IO包中去除还完全不影响IO包的结构却让其更“纯洁”――纯洁的Decorator模式。PrintStream也可以认为是一个辅助工具。主要可以向其他输出流或者FileInputStream写入数据本身内部实现还是带缓冲的。本质上是对其它流的综合运用的一个工具而已。一样可以踢出IO包!Systemout和Systemout就是PrintStream的实例!蓝色的部分是IO字节流的主要组成部分存在极强的对称关系。关于搭配使用的三对类补充一下:ObjectInputStreamObjectOutputStream和DataInputStreamDataOutputStream主要是要求写对象数据和读对象数据的次序要保持一致否则轻则不能得到正确的数据重则抛出异常(一般会如此)PipedInputStreamPipedOutputStream在创建时一般就一起创建调用它们的读写方法时会检查对方是否存在或者关闭!道理极其简单――对方都不在了怎么交互啊!字节流与字符流从上面我们可以看出IO中的字节流是极其复杂的存在大量的类到目前为止还没有真正使用它们使用它们应该也是极其复杂的吧!JDK后Sun对IO库进行了重大的改进。看到Reader和Writer类时大多数人的第一个感觉(不要太相信感觉哦!感觉也许会欺骗你的!)就是它们是用来替换原来的InputStream和OutputStream类。有新的类干吗还使用旧的呢!?但实情并非如此。尽管Sun不建议使用原始的流库中的某些功能但原来的流依然得到了保留不仅为了保持向后兼容主要原因是新库不是旧库的替代而是对旧库的增强。从以下两点可以明显地看出:()在老式的类层次结构里加入了新的类这表明Sun公司没有放弃老式流库的意图。()在许多情况下新库中类的使用需要联合老结构中的类。为达到这个目的需要使用一些“桥”类如:InputStreamReader将一个InputStream转换成ReaderOutputStreamWriter将一个OutputStream转换成Writer。那么Sun为什么在Java里添加了Reader和Writer层次最重要的原因便是国际化(Internationalization――in)的需求。老式IO流层次结构只支持位字节流不能很好地控制位的Unicode字符。Java本身支持UnicodeSun又一致吹嘘其支持Unicode因此有必要实现一个支持Unicode的流的层次结构所以出现了Reader和Writer层次以提供对所有IO操作中的Unicode的支持。除此之外新库也对速度进行了优化可比旧库更快地运行。位的字节流和位的字符流的对应关系可以从ByteInputStreamByteOutputStream与CharArrayInputStreamCharArrayOutputStream的对应关系中看出端倪。(还没看出来啊!赶紧去看看Java的基本数据类型)。因此在Java的IO体系中存在字节流和字符流的对应关系。下面就看看字符流吧!IOIOIOIO中的输入字符流下面是IO中输入字符流的继承图。•Reader•BufferedReader•LineNumberReaderCharArrayReaderFilterReaderPushbackReaderInputStreamReaderFileReaderPipedReaderStringReader在上面的关系图中可以看出:Reader是所有的输入字符流的父类它是一个抽象类。CharReader、StringReader是两种基本的介质流它们分别将Char数组、String中读取数据。PipedReader是从与其它线程共用的管道中读取数据。BufferedReader很明显就是一个装饰器它和其子类负责装饰其它Reader对象。FilterReader是所有自定义具体装饰流的父类其子类PushbackReader对Reader对象进行装饰会增加一个行号。InputStreamReader是一个连接字节流和字符流的桥梁它将字节流转变为字符流。FileReader可以说是一个达到此功能、常用的工具类在其源代码中明显使用了将FileInputStream转变为Reader的方法。我们可以从这个类中得到一定的技巧。Reader中各个类的用途和使用方法基本和InputStream中的类使用一致。后面会有Reader与InputStream的对应关系。IOIOIOIO中的输出字符流下面是IO中输出字符流的继承图。•Writer•BufferedWriterCharArrayWriterFilterWriterOutputStreamWriter•FileWriterPipedWriterPrintWriterStringWriter在上面的关系图中可以看出:Writer是所有的输出字符流的父类它是一个抽象类。CharArrayWriter、StringWriter是两种基本的介质流它们分别向Char数组、String中写入数据。PipedWriter是向与其它线程共用的管道中写入数据BufferedWriter是一个装饰器为Writer提供缓冲功能。PrintWriter和PrintStream极其类似功能和使用也非常相似。OutputStreamWriter是OutputStream到Writer转换的桥梁它的子类FileWriter其实就是一个实现此功能的具体类(具体可以研究一下SourceCode)。功能和使用和OutputStream极其类似后面会有它们的对应图。字符流的输入与输出的对应下图为字符流的输入与输出的对应关系图:对应关系和字节流的输入输出基本一致不必多说了吧!在下面的源代码阅读部分会仔细研究一些!字节流和字符流的对应Java的IO中存在输入、输出的对应和字节流和字符流的对应下面就看看字节流和字符流的对应吧!输入的对应输入的对应输入的对应输入的对应下图是IO中字节输入流与字符输入流的对应图:蓝色的表示对应的部分红色的表示不对应的部分。至于为什么不对应还是你自己多看看源代码、多考虑考虑吧!还要强调一点就是即使对应它们的继承关系也是不太对应的。输出的对应输出的对应输出的对应输出的对应下图是IO中字节输出流与字符输出流的对应图:不多说了!等讲述了Adapter和Decorator模式会基本明白IO架构的!通过几个实例一般就可以使用了!从InputStreamInputStreamInputStreamInputStream到ByteArrayInputStreamByteArrayInputStreamByteArrayInputStreamByteArrayInputStream江苏无锡缪小东本篇主要分析:如何将byte数组适配至ByteArrayInputStream对应与IO部分的适配器模式BufferedInputStream的工作原理对应于IO的装饰器模式会首先研究InputStream和FilterInputStream的源代码同时会将要谈谈软件设计中的缓存相关的知识。后面专门一章分析PipedInputStream和PipedOutStream简单谈谈管道相关的知识以及软件架构的想法。InputStreamInputStreamInputStreamInputStreamInputStream是输入字节流部分装饰器模式的顶层类。主要规定了输入字节流的公共方法。packagejavaiopublicabstractclassInputStreamimplementsCloseable{privatestaticfinalintSKIPBUFFERSIZE=用于skip方法和skipBuffer相关privatestaticbyteskipBufferskipBufferisinitializedinskip(long),ifneededpublicabstractintread()throwsIOException从输入流中读取下一个字节正常返回到达文件的末尾返回在流中还有数据但是没有读到时该方法会阻塞(block)JavaIO和NewIO的区别就是阻塞流和非阻塞流抽象方法哦!不同的子类不同的实现哦!将流中的数据读入放在byte数组的第off个位置先后的len个位置中放回值为放入字节的个数。publicintread(byteb,intoff,intlen)throwsIOException{if(b==){thrownewPointerException()}elseif(off<||len<||len>blengthoff){thrownewIndexOutOfBoundsException()}elseif(len==){return}检查输入是否正常。一般情况下检查输入是方法设计的第一步intc=read()读取下一个字节if(c==){return}到达文件的末端返回boff=(byte)c放回的字节downcastinti=已经读取了一个字节try{for(i<leni){最多读取len个字节所以要循环len次c=read()每次循环从流中读取一个字节由于read方法阻塞所以read(byte,int,int)也会阻塞if(c==){break}到达末尾理所当然放回boffi=(byte)c读到就放入byte数组中}}catch(IOExceptionee){}returni上面这个部分其实还有一点比较重要inti=在循环的外围或许你经常见到或许你只会在循环是才声明为什么呢?声明在外面增大了变量的生存周期(在循环外面)所以后面可以return返回极其一般的想法。在类成员变量生命周期中使用同样的理念。在软件设计中类和类的关系中也是一样的。}这个方法在利用抽象方法read某种意义上简单的Templete模式。publicintread(byteb)throwsIOException{returnread(b,,blength)}利用上面的方法read(byteb)publiclongskip(longn)throwsIOException{longremaining=n方法内部使用的、表示要跳过的字节数目使用它完成一系列字节读取的循环intnrif(skipBuffer==)skipBuffer=newbyteSKIPBUFFERSIZE初始化一个跳转的缓存bytelocalSkipBuffer=skipBuffer本地化的跳转缓存if(n<=){return}检查输入参数应该放在方法的开始while(remaining>){一共要跳过n个每次跳过部分循环nr=read(localSkipBuffer,,(int)Mathmin(SKIPBUFFERSIZE,remaining))利用上面的read(byte,int,int)方法尽量读取n个字节if(nr<){break}读到流的末端则返回remaining=nr没有完全读到需要的则继续循环}returnnremaining返回时要么全部读完要么因为到达文件末端读取了部分}publicintavailable()throwsIOException{查询流中还有多少可以读取的字节return}该方法不会block。在java中抽象类方法的实现一般有以下几种方式:抛出异常(javautil)“弱”实现。象上面这种。子类在必要的时候覆盖它。“空”实现。下面有例子。publicvoidclose()throwsIOException{}关闭当前流、同时释放与此流相关的资源publicsynchronizedvoidmark(intreadlimit){}在当前位置对流进行标记必要的时候可以使用reset方法返回。markSupport可以查询当前流是否支持markpublicsynchronizedvoidreset()throwsIOException{thrownewIOException("markresetnotsupported")}对mark过的流进行复位。只有当流支持mark时才可以使用此方法。看看mark、available和reset方法。体会为什么?!publicbooleanmarkSupported(){查询是否支持markreturnfalse}绝大部分不支持因此提供默认实现返回false。子类有需要可以覆盖。}FilterInputStreamFilterInputStreamFilterInputStreamFilterInputStream这是字节输入流部分装饰器模式的核心。是我们在装饰器模式中的Decorator对象主要完成对其它流装饰的基本功能。下面是它的源代码:packagejavaio该类对被装饰的流进行基本的包裹。不增加额外的功能。客户在需要的时候可以覆盖相应的方法。具体覆盖可以在ByteInputStream中看到!publicclassFilterInputStreamextendsInputStream{protectedvolatileInputStreamin将要被装饰的字节输入流protectedFilterInputStream(InputStreamin){通过构造方法传入此被装饰的流thisin=in}装饰器的代码特征:被装饰的对象一般是装饰器的成员变量上面几行可以看出。下面这些方法完成最小的装饰――装饰只是调用被装饰流的方法而已publicintread()throwsIOException{returninread()}publicintread(byteb)throwsIOException{returnread(b,,blength)}publicintread(byteb,intoff,intlen)throwsIOException{returninread(b,off,len)}publiclongskip(longn)throwsIOException{returninskip(n)}publicintavailable()throwsIOException{returninavailable()}publicvoidclose()throwsIOException{inclose()}publicsynchronizedvoidmark(intreadlimit){inmark(readlimit)}publicsynchronizedvoidreset()throwsIOException{inreset()}publicbooleanmarkSupported(){returninmarkSupported()}以上的方法都是通过调用被装饰对象in完成的。没有添加任何额外功能装饰器模式中的Decorator对象不增加被装饰对象的功能。它是装饰器模式中的核心。更多关于装饰器模式的理论请阅读博客中的文章。}以上分析了所有字节输入流的公共父类InputStream和装饰器类FilterInputStream类。他们是装饰器模式中两个重要的类。更多细节请阅读博客中装饰器模式的文章。下面将讲解一个具体的流ByteArrayInputStream不过它是采用适配器设计模式。ByteArrayByteArrayByteArrayByteArray到ByteArrayInputStreamByteArrayInputStreamByteArrayInputStreamByteArrayInputStream的适配ByteArrayInputStream内部有一个byte类型的buffer。很典型的适配器模式的应用――将byte数组适配流的接口。下面是源代码分析:packagejavaiopublicclassByteArrayInputStreamextendsInputStream{protectedbytebuf内部的buffer一般通过构造器输入protectedintpos当前位置的cursor。从至byte数组的长度。bytepos就是read方法读取的字节protectedintmark=mark的位置。protectedintcount流中字节的数目。不一定与byte的长度一致???publicByteArrayInputStream(bytebuf){从一个byte创建一个ByteArrayInputStreamthisbuf=buf初始化流中的各个成员变量thispos=thiscount=buflengthcount就等于buflength}publicByteArrayInputStream(bytebuf,intoffset,intlength){构造器thisbuf=bufthispos=offset与上面不同thiscount=Mathmin(offsetlength,buflength)thismark=offset与上面不同}publicsynchronizedintread(){从流中读取下一个字节return(pos<count)(bufposxff):返回下一个位置的字节流中没有数据则返回}下面这个方法很有意思!从InputStream中可以看出其提供了该方法的实现。为什么ByteArrayInputStream要覆盖此方法呢?同样的我们在JavaCollectionsFramework中可以看到:AbstractCollection利用iterator实现了Collecion接口的很多方法。但是在ArrayList中却有很多被子类覆盖了。为什么如此呢??publicsynchronizedintread(byteb,intoff,intlen){if(b==){首先检查输入参数的状态是否正确thrownewPointerException()}elseif(off<||len<||len>blengthoff){thrownewIndexOutOfBoundsException()}if(pos>=count){return}if(poslen>count){len=countpos}if(len<=){return}Systemarraycopy(buf,pos,b,off,len)java中提供数据复制的方法pos=lenreturnlen}出于速度的原因!他们都用到Systemarraycopy方法。想想为什么?某些时候父类不能完全实现子类的功能父类的实现一般比较通用。当子类有更有效的方法时我们会覆盖这些方法。这样可是不太OO的哦!下面这个方法在InputStream中也已经实现了。但是当时是通过将字节读入一个buffer中实现的好像效率低了一点。看看下面这段代码是否极其简单呢?!publicsynchronizedlongskip(longn){if(posn>count){n=countpos}当前位置可以跳跃的字节数目if(n<){return}小于则不可以跳跃pos=n跳跃后当前位置变化returnn}比InputStream中的方法简单、高效吧!publicsynchronizedintavailable(){returncountpos}查询流中还有多少字节没有读取。在我们的ByteArrayInputStream中就是当前位置以后字节的数目。publicbooleanmarkSupported(){returntrue}ByteArrayInputStream支持mark所以返回truepublicvoidmark(intreadAheadLimit){mark=pos}在流中当前位置mark。在我们的ByteArrayInputStream中就是将当前位置赋给mark变量。读取流中的字节就是读取字节数组中当前位置向后的的字节。publicsynchronizedvoidreset(){pos=mark}重置流。即回到mark的位置。publicvoidclose()throwsIOException{}关闭ByteArrayInputStream不会产生任何动作。为什么?仔细考虑吧!!}上面我们分小节讲了装饰器模式中的公共父类(对应于输入字节流的InputStream)、Decorator(对应于输入字节流的FilterInputStream)和基本被装饰对象(对应于输入字节流的媒体字节流)。下面我们就要讲述装饰器模式中的具体的包装器(对应于输入字节流的包装器流)。BufferedInputStreamBufferedInputStreamBufferedInputStreamBufferedInputStream原理及其在软件硬件中的应用原理及其在软件硬件中的应用原理及其在软件硬件中的应用原理及其在软件硬件中的应用read――read(byte,int,int)BufferedInputStream《由一个简单的程序谈起》CachePoolSplingPrinter(最近比较忙不讲了!)BufferedInputStreamBufferedInputStreamBufferedInputStreamBufferedInputStream源代码分析源代码分析源代码分析源代码分析packagejavaioimportjavautilconcurrentatomicAtomicReferenceFieldUpdater该类主要完成对被包装流加上一个缓存的功能publicclassBufferedInputStreamextendsFilterInputStream{privatestaticintdefaultBufferSize=默认缓存的大小protectedvolatilebytebuf内部的缓存protectedintcountbuffer的大小protectedintposbuffer中cursor的位置protectedintmarkpos=mark的位置protectedintmarklimitmark的范围原子性更新。和一致性编程相关privatestaticfinalAtomicReferenceFieldUpdater<BufferedInputStream,byte>bufUpdater=AtomicReferenceFieldUpdaternewUpdater(BufferedInputStreamclass,byteclass,"buf")privateInputStreamgetInIfOpen()throwsIOException{检查输入流是否关闭同时返回被包装流InputStreaminput=inif(input==)thrownewIOException("Streamclosed")returninput}privatebytegetBufIfOpen()throwsIOException{检查buffer的状态同时返回缓存bytebuffer=bufif(buffer==)thrownewIOException("Streamclosed")不太可能发生的状态returnbuffer}publicBufferedInputStream(InputStreamin){构造器this(in,defaultBufferSize)指定默认长度的buffer}publicBufferedInputStream(InputStreamin,intsize){构造器super(in)if(size<=){检查输入参数thrownewIllegalArgumentException("Buffersize<=")}buf=newbytesize创建指定长度的buffer}从流中读取数据填充如缓存中。privatevoidfill()throwsIOException{bytebuffer=getBufIfOpen()得到bufferif(markpos<)pos=mark位置小于此时pos为elseif(pos>=bufferlength)pos大于buffer的长度if(markpos>){intsz=posmarkpos

用户评价(0)

关闭

新课改视野下建构高中语文教学实验成果报告(32KB)

抱歉,积分不足下载失败,请稍后再试!

提示

试读已结束,如需要继续阅读或者下载,敬请购买!

文档小程序码

使用微信“扫一扫”扫码寻找文档

1

打开微信

2

扫描小程序码

3

发布寻找信息

4

等待寻找结果

我知道了
评分:

/40

Java_IO完全总结

VIP

在线
客服

免费
邮箱

爱问共享资料服务号

扫描关注领取更多福利