下载

1下载券

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

上传资料

关闭

关闭

关闭

封号提示

内容

首页 第10章 Java IO系统

第10章 Java IO系统.doc

第10章 Java IO系统

liuqingqing
2013-07-11 0人阅读 举报 0 0 0 暂无简介

简介:本文档为《第10章 Java IO系统doc》,可适用于高等教育领域

第章JavaIO系统“对语言设计人员来说创建好的输入/输出系统是一项特别困难的任务。”由于存在大量不同的设计方案所以该任务的困难性是很容易证明的。其中最大的挑战似乎是如何覆盖所有可能的因素。不仅有三种不同的种类的IO需要考虑(文件、控制台、网络连接)而且需要通过大量不同的方式与它们通信(顺序、随机访问、二进制、字符、按行、按字等等)。Java库的设计者通过创建大量类来攻克这个难题。事实上Java的IO系统采用了如此多的类以致刚开始会产生不知从何处入手的感觉(具有讽刺意味的是Java的IO设计初衷实际要求避免过多的类)。从Java升级到Java后IO库的设计也发生了显著的变化。此时并非简单地用新库替换旧库Sun的设计人员对原来的库进行了大手笔的扩展添加了大量新的内容。因此我们有时不得不混合使用新库与旧库产生令人无奈的复杂代码。本章将帮助大家理解标准Java库内的各种IO类并学习如何使用它们。本章的第一部分将介绍“旧”的JavaIO流库因为现在有大量代码仍在使用那个库。本章剩下的部分将为大家引入JavaIO库的一些新特性。注意若用Java编译器来编译本章第一部分介绍的部分代码可能会得到一条“不建议使用该特性”(Deprecatedfeature)警告消息。代码仍然能够使用编译器只是建议我们换用本章后面要讲述的一些新特性。但我们这样做是有价值的因为可以更清楚地认识老方法与新方法之间的一些差异从而加深我们的理解(并可顺利阅读为Java写的代码)。输入和输出可将Java库的IO类分割为输入与输出两个部分这一点在用Web浏览器阅读联机Java类文档时便可知道。通过继承从InputStream(输入流)衍生的所有类都拥有名为read()的基本方法用于读取单个字节或者字节数组。类似地从OutputStream衍生的所有类都拥有基本方法write()用于写入单个字节或者字节数组。然而我们通常不会用到这些方法它们之所以存在是因为更复杂的类可以利用它们以便提供一个更有用的接口。因此我们很少用单个类创建自己的系统对象。一般情况下我们都是将多个对象重叠在一起提供自己期望的功能。我们之所以感到Java的流库(StreamLibrary)异常复杂正是由于为了创建单独一个结果流却需要创建多个对象的缘故。很有必要按照功能对类进行分类。库的设计者首先决定与输入有关的所有类都从InputStream继承而与输出有关的所有类都从OutputStream继承。InputStream的类型InputStream的作用是标志那些从不同起源地产生输入的类。这些起源地包括(每个都有一个相关的InputStream子类):()字节数组()String对象()文件()“管道”它的工作原理与现实生活中的管道类似:将一些东西置入一端它们在另一端出来。()一系列其他流以便我们将其统一收集到单独一个流内。()其他起源地如Internet连接等(将在本书后面的部分讲述)。除此以外FilterInputStream也属于InputStream的一种类型用它可为“破坏器”类提供一个基础类以便将属性或者有用的接口同输入流连接到一起。这将在以后讨论。表InputStream的类型类功能构建器参数/如何使用ByteArrayInputStream允许内存中的一个缓冲区作为InputStream使用从中提取字节的缓冲区/作为一个数据源使用。通过将其同一个FilterInputStream对象连接可提供一个有用的接口StringBufferInputStream将一个String转换成InputStream一个String(字串)。基础的实施方案实际采用一个StringBuffer(字串缓冲)/作为一个数据源使用。通过将其同一个FilterInputStream对象连接可提供一个有用的接口FileInputStream用于从文件读取信息代表文件名的一个String或者一个File或FileDescriptor对象/作为一个数据源使用。通过将其同一个FilterInputStream对象连接可提供一个有用的接口PipedInputString产生为相关的PipedOutputStream写的数据。实现了“管道化”的概念PipedOutputStream/作为一个数据源使用。通过将其同一个FilterInputStream对象连接可提供一个有用的接口SequenceInputStream将两个或更多的InputStream对象转换成单个InputStream使用两个InputStream对象或者一个Enumeration用于InputStream对象的一个容器/作为一个数据源使用。通过将其同一个FilterInputStream对象连接可提供一个有用的接口FilterInputStream对作为破坏器接口使用的类进行抽象那个破坏器为其他InputStream类提供了有用的功能。参见表参见表/参见表ClassFunctionConstructorArgumentsHowtouseitByteArrayInputStreamAllowsabufferinmemorytobeusedasanInputStreamThebufferfromwhichtoextractthebytesAsasourceofdataConnectittoaFilterInputStreamobjecttoprovideausefulinterfaceStringBufferInputStreamConvertsaStringintoanInputStreamAStringTheunderlyingimplementationactuallyusesaStringBufferAsasourceofdataConnectittoaFilterInputStreamobjecttoprovideausefulinterfaceFileInputStreamForreadinginformationfromafileAStringrepresentingthefilename,oraFileorFileDescriptorobjectAsasourceofdataConnectittoaFilterInputStreamobjecttoprovideausefulinterfacePipedInputStreamProducesthedatathat’sbeingwrittentotheassociatedPipedOutputStreamImplementsthe“piping”conceptPipedOutputStreamAsasourceofdatainmultithreadingConnectittoaFilterInputStreamobjecttoprovideausefulinterfaceSequenceInputStreamConvertstwoormoreInputStreamobjectsintoasingleInputStreamTwoInputStreamobjectsoranEnumerationforacontainerofInputStreamobjectsAsasourceofdataConnectittoaFilterInputStreamobjecttoprovideausefulinterfaceFilterInputStreamAbstractclasswhichisaninterfacefordecoratorsthatprovideusefulfunctionalitytotheotherInputStreamclassesSeeTableSeeTableSeeTableOutputStream的类型这一类别包括的类决定了我们的输入往何处去:一个字节数组(但没有String假定我们可用字节数组创建一个)一个文件或者一个“管道”。除此以外FilterOutputStream为“破坏器”类提供了一个基础类它将属性或者有用的接口同输出流连接起来。这将在以后讨论。表OutputStream的类型类功能构建器参数/如何使用ByteArrayOutputStream在内存中创建一个缓冲区。我们发送给流的所有数据都会置入这个缓冲区。可选缓冲区的初始大小/用于指出数据的目的地。若将其同FilterOutputStream对象连接到一起可提供一个有用的接口FileOutputStream将信息发给一个文件用一个String代表文件名或选用一个File或FileDescriptor对象/用于指出数据的目的地。若将其同FilterOutputStream对象连接到一起可提供一个有用的接口PipedOutputStream我们写给它的任何信息都会自动成为相关的PipedInputStream的输出。实现了“管道化”的概念PipedInputStream/为多线程处理指出自己数据的目的地/将其同FilterOutputStream对象连接到一起便可提供一个有用的接口FilterOutputStream对作为破坏器接口使用的类进行抽象处理那个破坏器为其他OutputStream类提供了有用的功能。参见表参见表/参见表ClassFunctionConstructorArgumentsHowtouseitByteArrayOutputStreamCreatesabufferinmemoryAllthedatathatyousendtothestreamisplacedinthisbufferOptionalinitialsizeofthebufferTodesignatethedestinationofyourdataConnectittoaFilterOutputStreamobjecttoprovideausefulinterfaceFileOutputStreamForsendinginformationtoafileAStringrepresentingthefilename,oraFileorFileDescriptorobjectTodesignatethedestinationofyourdataConnectittoaFilterOutputStreamobjecttoprovideausefulinterfacePipedOutputStreamAnyinformationyouwritetothisautomaticallyendsupasinputfortheassociatedPipedInputStreamImplementsthe“piping”conceptPipedInputStreamTodesignatethedestinationofyourdataformultithreadingConnectittoaFilterOutputStreamobjecttoprovideausefulinterfaceFilterOutputStreamAbstractclasswhichisaninterfacefordecoratorsthatprovideusefulfunctionalitytotheotherOutputStreamclassesSeeTableSeeTableSeeTable增添属性和有用的接口利用层次化对象动态和透明地添加单个对象的能力的做法叫作“装饰器”(Decorator)方案“方案”属于本书第章的主题(注释①)。装饰器方案规定封装于初始化对象中的所有对象都拥有相同的接口以便利用装饰器的“透明”性质我们将相同的消息发给一个对象无论它是否已被“装饰”。这正是在JavaIO库里存在“过滤器”(Filter)类的原因:抽象的“过滤器”类是所有装饰器的基础类(装饰器必须拥有与它装饰的那个对象相同的接口但装饰器亦可对接口作出扩展这种情况见诸于几个特殊的“过滤器”类中)。子类处理要求大量子类对每种可能的组合提供支持时便经常会用到装饰器由于组合形式太多造成子类处理变得不切实际。JavaIO库要求许多不同的特性组合方案这正是装饰器方案显得特别有用的原因。但是装饰器方案也有自己的一个缺点。在我们写一个程序的时候装饰器为我们提供了大得多的灵活性(因为可以方便地混合与匹配属性)但它们也使自己的代码变得更加复杂。原因在于JavaIO库操作不便我们必须创建许多类“核心”IO类型加上所有装饰器才能得到自己希望的单个IO对象。FilterInputStream和FilterOutputStream(这两个名字不十分直观)提供了相应的装饰器接口用于控制一个特定的输入流(InputStream)或者输出流(OutputStream)。它们分别是从InputStream和OutputStream衍生出来的。此外它们都属于抽象类在理论上为我们与一个流的不同通信手段都提供了一个通用的接口。事实上FilterInputStream和FilterOutputStream只是简单地模仿了自己的基础类它们是一个装饰器的基本要求。通过FilterInputStream从InputStream里读入数据FilterInputStream类要完成两件全然不同的事情。其中DataInputStream允许我们读取不同的基本类型数据以及String对象(所有方法都以“read”开头比如readByte()readFloat()等等)。伴随对应的DataOutputStream我们可通过数据“流”将基本类型的数据从一个地方搬到另一个地方。这些“地方”是由表总结的那些类决定的。若读取块内的数据并自己进行解析就不需要用到DataInputStream。但在其他许多情况下我们一般都想用它对自己读入的数据进行自动格式化。剩下的类用于修改InputStream的内部行为方式:是否进行缓冲是否跟踪自己读入的数据行以及是否能够推回一个字符等等。后两种类看起来特别象提供对构建一个编译器的支持(换言之添加它们为了支持Java编译器的构建)所以在常规编程中一般都用不着它们。也许几乎每次都要缓冲自己的输入无论连接的是哪个IO设备。所以IO库最明智的做法就是将未缓冲输入作为一种特殊情况处理同时将缓冲输入接纳为标准做法。表FilterInputStream的类型类功能构建器参数/如何使用DataInputStream与DataOutputStream联合使用使自己能以机动方式读取一个流中的基本数据类型(intcharlong等等)InputStream包含了一个完整的接口以便读取基本数据类型BufferedInputStream避免每次想要更多数据时都进行物理性的读取告诉它“请先在缓冲区里找”InputStream没有可选的缓冲区大小/本身并不能提供一个接口只是发出使用缓冲区的要求。要求同一个接口对象连接到一起LineNumberInputStream跟踪输入流中的行号可调用getLineNumber()以及setLineNumber(int)只是添加对数据行编号的能力所以可能需要同一个真正的接口对象连接PushbackInputStream有一个字节的后推缓冲区以便后推读入的上一个字符InputStream/通常由编译器在扫描器中使用因为Java编译器需要它。一般不在自己的代码中使用通过FilterOutputStream向OutputStream里写入数据与DataInputStream对应的是DataOutputStream后者对各个基本数据类型以及String对象进行格式化并将其置入一个数据“流”中以便任何机器上的DataInputStream都能正常地读取它们。所有方法都以“wirte”开头例如writeByte()writeFloat()等等。若想进行一些真正的格式化输出比如输出到控制台请使用PrintStream。利用它可以打印出所有基本数据类型以及String对象并可采用一种易于查看的格式。这与DataOutputStream正好相反后者的目标是将那些数据置入一个数据流中以便DataInputStream能够方便地重新构造它们。Systemout静态对象是一个PrintStream。PrintStream内两个重要的方法是print()和println()。它们已进行了覆盖处理可打印出所有数据类型。print()和println()之间的差异是后者在操作完毕后会自动添加一个新行。BufferedOutputStream属于一种“修改器”用于指示数据流使用缓冲技术使自己不必每次都向流内物理性地写入数据。通常都应将它应用于文件处理和控制器IO。表FilterOutputStream的类型类功能构建器参数/如何使用DataOutputStream与DataInputStream配合使用以便采用方便的形式将基本数据类型(intcharlong等)写入一个数据流OutputStream/包含了完整接口以便我们写入基本数据类型PrintStream用于产生格式化输出。DataOutputStream控制的是数据的“存储”而PrintStream控制的是“显示”OutputStream可选一个布尔参数指示缓冲区是否与每个新行一同刷新/对于自己的OutputStream对象应该用“final”将其封闭在内。可能经常都要用到它BufferedOutputStream用它避免每次发出数据的时候都要进行物理性的写入要求它“请先在缓冲区里找”。可调用flush()对缓冲区进行刷新OutputStream可选缓冲区大小/本身并不能提供一个接口只是发出使用缓冲区的要求。需要同一个接口对象连接到一起本身的缺陷:RandomAccessFileRandomAccessFile用于包含了已知长度记录的文件以便我们能用seek()从一条记录移至另一条然后读取或修改那些记录。各记录的长度并不一定相同只要知道它们有多大以及置于文件何处即可。首先我们有点难以相信RandomAccessFile不属于InputStream或者OutputStream分层结构的一部分。除了恰巧实现了DataInput以及DataOutput(这两者亦由DataInputStream和DataOutputStream实现)接口之外它们与那些分层结构并无什么关系。它甚至没有用到现有InputStream或OutputStream类的功能采用的是一个完全不相干的类。该类属于全新的设计含有自己的全部(大多数为固有)方法。之所以要这样做是因为RandomAccessFile拥有与其他IO类型完全不同的行为因为我们可在一个文件里向前或向后移动。不管在哪种情况下它都是独立运作的作为Object的一个“直接继承人”使用。从根本上说RandomAccessFile类似DataInputStream和DataOutputStream的联合使用。其中getFilePointer()用于了解当前在文件的什么地方seek()用于移至文件内的一个新地点而length()用于判断文件的最大长度。此外构建器要求使用另一个自变量(与C的fopen()完全一样)指出自己只是随机读("r")还是读写兼施("rw")。这里没有提供对“只写文件”的支持。也就是说假如是从DataInputStream继承的那么RandomAccessFile也有可能能很好地工作。还有更难对付的。很容易想象我们有时要在其他类型的数据流中搜索比如一个ByteArrayInputStream但搜索方法只有RandomAccessFile才会提供。而后者只能针对文件才能操作不能针对数据流操作。此时BufferedInputStream确实允许我们标记一个位置(使用mark()它的值容纳于单个内部变量中)并用reset()重设那个位置。但这些做法都存在限制并不是特别有用。File类File类有一个欺骗性的名字通常会认为它对付的是一个文件但实情并非如此。它既代表一个特定文件的名字也代表目录内一系列文件的名字。若代表一个文件集便可用list()方法查询这个集返回的是一个字串数组。之所以要返回一个数组而非某个灵活的集合类是因为元素的数量是固定的。而且若想得到一个不同的目录列表只需创建一个不同的File对象即可。事实上“FilePath”(文件路径)似乎是一个更好的名字。本节将向大家完整地例示如何使用这个类其中包括相关的FilenameFilter(文件名过滤器)接口。目录列表器现在假设我们想观看一个目录列表。可用两种方式列出File对象。若在不含自变量(参数)的情况下调用list()会获得File对象包含的一个完整列表。然而若想对这个列表进行某些限制就需要使用一个“目录过滤器”该类的作用是指出应如何选择File对象来完成显示。下面是用于这个例子的代码(或在执行该程序时遇到困难请参考第章小节“赋值”)::c:DirListjavaDisplaysdirectorylistingimportjavaio*importjavautil*importcombruceeckelutil*publicclassDirList{publicstaticvoidmain(Stringargs){Filepath=newFile("")Stringlistif(argslength==)list=pathlist()elselist=pathlist(newDirFilter(args))Arrayssort(list,newAlphabeticComparator())for(inti=i<listlengthi)Systemoutprintln(listi)}}classDirFilterimplementsFilenameFilter{StringafnDirFilter(Stringafn){thisafn=afn}publicbooleanaccept(Filedir,Stringname){Strippathinformation:Stringf=newFile(name)getName()returnfindexOf(afn)!=}}:~DirFilter类“实现”了interfaceFilenameFilter(关于接口的问题已在第章进行了详述)。下面让我们看看FilenameFilter接口有多么简单:publicinterfaceFilenameFilter{booleanaccept(文件目录,字串名)}它指出这种类型的所有对象都提供了一个名为accept()的方法。之所以要创建这样的一个类背后的全部原因就是把accept()方法提供给list()方法使list()能够“回调”accept()从而判断应将哪些文件名包括到列表中。因此通常将这种技术称为“回调”有时也称为“算子”(也就是说DirFilter是一个算子因为它唯一的作用就是容纳一个方法)。由于list()采用一个FilenameFilter对象作为自己的自变量使用所以我们能传递实现了FilenameFilter的任何类的一个对象用它决定(甚至在运行期)list()方法的行为方式。回调的目的是在代码的行为上提供更大的灵活性。通过DirFilter我们看出尽管一个“接口”只包含了一系列方法但并不局限于只能写那些方法(但是至少必须提供一个接口内所有方法的定义。在这种情况下DirFilter构建器也会创建)。accept()方法必须接纳一个File对象用它指示用于寻找一个特定文件的目录并接纳一个String其中包含了要寻找之文件的名字。可决定使用或忽略这两个参数之一但有时至少要使用文件名。记住list()方法准备为目录对象中的每个文件名调用accept()核实哪个应包含在内具体由accept()返回的“布尔”结果决定。为确定我们操作的只是文件名其中没有包含路径信息必须采用String对象并在它的外部创建一个File对象。然后调用getName()它的作用是去除所有路径信息(采用与平台无关的方式)。随后accept()用String类的indexOf()方法检查文件名内部是否存在搜索字串"afn"。若在字串内找到afn那么返回值就是afn的起点索引但假如没有找到返回值就是。注意这只是一个简单的字串搜索例子未使用常见的表达式“通配符”方案比如"fobr*"这种方案更难实现。list()方法返回的是一个数组。可查询这个数组的长度然后在其中遍历选定数组元素。与C和C的类似行为相比这种于方法内外方便游历数组的行为无疑是一个显著的进步。匿名内部类下例用一个匿名内部类(已在第章讲述)来重写显得非常理想。首先创建了一个filter()方法它返回指向FilenameFilter的一个句柄::c:DirListjavaUsesanonymousinnerclassesimportjavaio*importjavautil*importcombruceeckelutil*publicclassDirList{publicstaticFilenameFilterfilter(finalStringafn){Creationofanonymousinnerclass:returnnewFilenameFilter(){Stringfn=afnpublicbooleanaccept(Filedir,Stringn){Strippathinformation:Stringf=newFile(n)getName()returnfindexOf(fn)!=}}Endofanonymousinnerclass}publicstaticvoidmain(Stringargs){Filepath=newFile("")Stringlistif(argslength==)list=pathlist()elselist=pathlist(filter(args))Arrayssort(list,newAlphabeticComparator())for(inti=i<listlengthi)Systemoutprintln(listi)}}:~注意filter()的自变量必须是final。这一点是匿名内部类要求的使其能使用来自本身作用域以外的一个对象。之所以认为这样做更好是由于FilenameFilter类现在同DirList紧密地结合在一起。然而我们可采取进一步的操作将匿名内部类定义成list()的一个参数使其显得更加精简。如下所示::c:DirListjavaBuildingtheanonymousinnerclass"inplace"importjavaio*importjavautil*importcombruceeckelutil*publicclassDirList{publicstaticvoidmain(finalStringargs){Filepath=newFile("")Stringlistif(argslength==)list=pathlist()elselist=pathlist(newFilenameFilter(){publicbooleanaccept(Filedir,Stringn){Stringf=newFile(n)getName()returnfindexOf(args)!=}})Arrayssort(list,newAlphabeticComparator())for(inti=i<listlengthi)Systemoutprintln(listi)}}:~main()现在的自变量是final因为匿名内部类直接使用args。这展示了如何利用匿名内部类快速创建精简的类以便解决一些复杂的问题。由于Java中的所有东西都与类有关所以它无疑是一种相当有用的编码技术。它的一个好处是将特定的问题隔离在一个地方统一解决。但在另一方面这样生成的代码不是十分容易阅读所以使用时必须慎重。顺序目录列表经常都需要文件名以排好序的方式提供。由于Java和Java都没有提供对排序的支持(从Java开始提供)所以必须用第章创建的SortVector将这一能力直接加入自己的程序。就象下面这样:页程序这里进行了另外少许改进。不再是将path(路径)和list(列表)创建为main()的本地变量它们变成了类的成员使它们的值能在对象“生存”期间方便地访问。事实上main()现在只是对类进行测试的一种方式。大家可以看到一旦列表创建完毕类的构建器就会自动开始对列表进行排序。这种排序不要求区分大小写所以最终不会得到一组全部单词都以大写字母开头的列表跟着是全部以小写字母开头的列表。然而我们注意到在以相同字母开头的一组文件名中大写字母是排在前面的这对标准的排序来说仍是一种不合格的行为。Java已成功解决了这个问题。检查与创建目录File类并不仅仅是对现有目录路径、文件或者文件组的一个表示。亦可用一个File对象新建一个目录甚至创建一个完整的目录路径假如它尚不存在的话。亦可用它了解文件的属性(长度、上一次修改日期、读/写属性等)检查一个File对象到底代表一个文件还是一个目录以及删除一个文件等等。下列程序完整展示了如何运用File类剩下的这些方法::c:MakeDirectoriesjavaDemonstratestheuseoftheFileclasstocreatedirectoriesandmanipulatefilesimportjavaio*publicclassMakeDirectories{privatefinalstaticStringusage="Usage:MakeDirectoriespathn""Createseachpathn""Usage:MakeDirectoriesdpathn""Deleteseachpathn""Usage:MakeDirectoriesrpathpathn""Renamesfrompathtopathn"privatestaticvoidusage(){Systemerrprintln(usage)Systemexit()}privatestaticvoidfileData(Filef){Systemoutprintln("Absolutepath:"fgetAbsolutePath()"nCanread:"fcanRead()"nCanwrite:"fcanWrite()"ngetName:"fgetName()"ngetParent:"fgetParent()"ngetPath:"fgetPath()"nlength:"flength()"nlastModified:"flastModified())if(fisFile())Systemoutprintln("it'safile")elseif(fisDirectory())Systemoutprintln("it'sadirectory")}publicstaticvoidmain(Stringargs){if(argslength<)usage()if(argsequals("r")){if(argslength!=)usage()Fileold=newFile(args),rname=newFile(args)oldrenameTo(rname)fileData(old)fileData(rname)returnExitmain}intcount=booleandel=falseif(argsequals("d")){countdel=true}for(count<argslengthcount){Filef=newFile(argscount)if(fexists()){Systemoutprintln(f"exists")if(del){Systemoutprintln("deleting"f)fdelete()}}else{Doesn'texistif(!del){fmkdirs()Systemoutprintln("created"f)}}fileData(f)}}}:~在fileData()中可看到应用了各种文件调查方法来显示与文件或目录路径有关的信息。main()应用的第一个方法是renameTo()利用它可以重命名(或移动)一个文件至一个全新的路径(该路径由参数决定)它属于另一个File对象。这也适用于任何长度的目录。若试验上述程序就可发现自己能制作任意复杂程度的一个目录路径因为mkdirs()会帮我们完成所有工作。在Java中d标志报告目录虽然已被删除但它依然存在但在Java中目录会被实际删除。IO流的典型应用尽管库内存在大量IO流类可通过多种不同的方式组合到一起但实际上只有几种方式才会经常用到。然而必须小心在意才能得到正确的组合。下面这个相当长的例子展示了典型IO配置的创建与使用可在写自己的代码时将其作为一个参考使用。注意每个配置都以一个注释形式的编号起头并提供了适当的解释信息。:c:IOStreamDemojavaTypicalIOstreamconfigurationsimportjavaio*publicclassIOStreamDemo{Throwexceptionstoconsole:publicstaticvoidmain(Stringargs)throwsIOException{Readinginputbylines:BufferedReaderin=newBufferedReader(newFileReader("IOStreamDemojava"))Strings,s=newString()while((s=inreadLine())!=)s=s"n"inclose()bReadingstandardinput:BufferedReaderstdin=newBufferedReader(newInputStreamReader(Systemin))Systemoutprint("Enteraline:")Systemoutprintln(stdinreadLine())InputfrommemoryStringReaderin=newStringReader(s)intcwhile((c=inread())!=)Systemoutprint((char)c)Formattedmemoryinputtry{DataInputStreamin=newDataInputStream(newByteArrayInputStream(sgetBytes()))while(true)Systemoutprint((char)inreadByte())}catch(EOFExceptione){Systemerrprintln("Endofstream")}Fileoutputtry{BufferedReaderin=newBufferedReader(newStringReader(s))PrintWriterout=newPrintWriter(newBufferedWriter(newFileWriter("IODemoout")))intlineCount=while((s=inreadLine())!=)outprintln(lineCount":"s)outclose()}catch(EOFExceptione){Systemerrprintln("Endofstream")}Storingrecoveringdatatry{DataOutputStreamout=newDataOutputStream(newBufferedOutputStream(newFileOutputStream("Datatxt")))outwriteDouble()outwriteChars("Thatwaspin")outwriteBytes("Thatwaspin")outclose()DataInputStreamin=newDataInputStream(newBufferedInputStream(newFileInputStream("Datatxt")))BufferedReaderinbr=newBufferedReader(newInputStreamReader(in))MustuseDataInputStreamfordata:Systemoutprintln(inreadDouble())Cannowusethe"proper"readLine():Systemoutprintln(inbrreadLine())ButthelinecomesoutfunnyTheonecreatedwithwriteBytesisOK:Systemoutprintln(inbrreadLine())}catch(EOFExceptione){Systemerrprintln("Endofstream")}ReadingwritingrandomaccessfilesRandomAccessFilerf=newRandomAccessFile("rtestdat","rw")for(inti=i<i)rfwriteDouble(i*)rfclose()rf=newRandomAccessFile("rtestdat","rw")rfseek(*)rfwriteDouble()rfclose()rf=newRandomAccessFile("rtestdat","r")for(inti=i<i)Systemoutprintln("Value"i":"rfreadDouble())rfclose()}}:~输入流当然我们经常想做的一件事情是将格式化的输出打印到控制台但那已在第章创建的combruceeckeltools中得到了简化。第到第部分演示了输入流的创建与使用(尽管第部分展示了将输出流作为一个测试工具的简单应用)。缓冲的输入文件为打开一个文件以便输入需要使用一个FileInputStream同时将一个String或File对象作为文件名使用。为提高速度最好先对文件进行缓冲处理从而获得用于一个BufferedInputStream的构建器的结果句柄。为了以格式化的形式读取输入数据我们将那个结果句柄赋给用于一个DataInputStream的构建器。DataInputStream是我们的最终(final)对象并是我们进行读取操作的接口。在这个例子中只用到了read

用户评价(0)

关闭

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

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

提示

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

评分:

/60

VIP

在线
客服

免费
邮箱

爱问共享资料服务号

扫描关注领取更多福利