友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!阅读过程发现任何错误请告诉我们,谢谢!! 报告错误
一世书城 返回本书目录 我的书架 我的书签 TXT全本下载 进入书吧 加入书签

Java编程思想第4版[中文版](PDF格式)-第98章

按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!




/作为一个数据源使用。通过将其同一个FilterInputStream 对象连接,可提供一个有用的接口  

PipedInputString 产生为相关的 PipedOutputStream 写的数据。实现了“管道化”的概念  

PipedOutputStream /作为一个数据源使用。通过将其同一个FilterInputStream 对象连接,可提供一个有用 

的接口  

SequenceInputStream 将两个或更多的 InputStream 对象转换成单个 InputStream 使用 两个InputStream对 

象或者一个 Enumeration,用于 InputStream对象的一个容器/作为一个数据源使用。通过将其同一个 

FilterInputStream 对象连接,可提供一个有用的接口  

FilterInputStream 对作为破坏器接口使用的类进行抽象;那个破坏器为其他 InputStream类提供了有用的 

功能。参见表 10。3 参见表 10。3 /参见表10。3  



10。1。2 OutputStream 的类型  



这一类别包括的类决定了我们的输入往何处去:一个字节数组(但没有String;假定我们可用字节数组创建 

一个);一个文件;或者一个“管道”。  

除此以外,FilterOutputStream 为“破坏器”类提供了一个基础类,它将属性或者有用的接口同输出流连接 

起来。这将在以后讨论。  

  

表 10。2 OutputStream 的类型  

  

类 功能 构建器参数/如何使用  

  

ByteArrayOutputStream 在内存中创建一个缓冲区。我们发送给流的所有数据都会置入这个缓冲区。 可选缓 

冲区的初始大小/用于指出数据的目的地。若将其同FilterOutputStream 对象连接到一起,可提供一个有用 

的接口  

FileOutputStream 将信息发给一个文件 用一个 String 代表文件名,或选用一个File 或FileDescriptor 对 

象/用于指出数据的目的地。若将其同FilterOutputStream 对象连接到一起,可提供一个有用的接口  

PipedOutputStream 我们写给它的任何信息都会自动成为相关的PipedInputStream 的输出。实现了“管道 

化”的概念 PipedInputStream /为多线程处理指出自己数据的目的地/将其同FilterOutputStream 对象连 

接到一起,便可提供一个有用的接口  

FilterOutputStream 对作为破坏器接口使用的类进行抽象处理;那个破坏器为其他 OutputStream 类提供了 

有用的功能。参见表 10。4 参见表 10。4 /参见表10。4  



10。2 增添属性和有用的接口  



利用层次化对象动态和透明地添加单个对象的能力的做法叫作“装饰器”(Decorator)方案—— “方案”属 

于本书第 16 章的主题(注释①)。装饰器方案规定封装于初始化对象中的所有对象都拥有相同的接口,以便 

利用装饰器的“透明”性质——我们将相同的消息发给一个对象,无论它是否已被“装饰”。这正是在Java  

IO库里存在“过滤器”(Filter)类的原因:抽象的“过滤器”类是所有装饰器的基础类(装饰器必须拥有 

与它装饰的那个对象相同的接口,但装饰器亦可对接口作出扩展,这种情况见诸于几个特殊的“过滤器”类 

中)。  

子类处理要求大量子类对每种可能的组合提供支持时,便经常会用到装饰器——由于组合形式太多,造成子 

类处理变得不切实际。Java IO 库要求许多不同的特性组合方案,这正是装饰器方案显得特别有用的原因。 

但是,装饰器方案也有自己的一个缺点。在我们写一个程序的时候,装饰器为我们提供了大得多的灵活性 

 (因为可以方便地混合与匹配属性),但它们也使自己的代码变得更加复杂。原因在于Java IO 库操作不 

便,我们必须创建许多类—— “核心”IO类型加上所有装饰器——才能得到自己希望的单个 IO 对象。  

FilterInputStream 和FilterOutputStream (这两个名字不十分直观)提供了相应的装饰器接口,用于控制 

一个特定的输入流(InputStream)或者输出流(OutputStream)。它们分别是从 InputStream和 

OutputStream 衍生出来的。此外,它们都属于抽象类,在理论上为我们与一个流的不同通信手段都提供了一 



                                                                       286 


…………………………………………………………Page 288……………………………………………………………

个通用的接口。事实上,FilterInputStream 和 FilterOutputStream 只是简单地模仿了自己的基础类,它们 

是一个装饰器的基本要求。  



10。2。1 通过 FilterInputStream 从 InputStream 里读入数据  



FilterInputStream 类要完成两件全然不同的事情。其中,DataInputStream 允许我们读取不同的基本类型数 

据以及 String 对象(所有方法都以“read ”开头,比如readByte(),readFloat()等等)。伴随对应的 

DataOutputStream,我们可通过数据“流”将基本类型的数据从一个地方搬到另一个地方。这些“地方”是 

由表10。1 总结的那些类决定的。若读取块内的数据,并自己进行解析,就不需要用到DataInputStream。但 

在其他许多情况下,我们一般都想用它对自己读入的数据进行自动格式化。  

剩下的类用于修改 InputStream 的内部行为方式:是否进行缓冲,是否跟踪自己读入的数据行,以及是否能 

够推回一个字符等等。后两种类看起来特别象提供对构建一个编译器的支持(换言之,添加它们为了支持 

Java 编译器的构建),所以在常规编程中一般都用不着它们。  

也许几乎每次都要缓冲自己的输入,无论连接的是哪个IO设备。所以 IO 库最明智的做法就是将未缓冲输入 

作为一种特殊情况处理,同时将缓冲输入接纳为标准做法。  

  

表 10。3 FilterInputStream 的类型  

  

类 功能 构建器参数/如何使用  

  

DataInputStream 与 DataOutputStream 联合使用,使自己能以机动方式读取一个流中的基本数据类型 

 (int,char,long 等等) InputStream/包含了一个完整的接口,以便读取基本数据类型  

BufferedInputStream 避免每次想要更多数据时都进行物理性的读取,告诉它“请先在缓冲区里找”  

InputStream,没有可选的缓冲区大小/本身并不能提供一个接口,只是发出使用缓冲区的要求。要求同一个 

接口对象连接到一起  

LineNumberInputStream 跟踪输入流中的行号;可调用 getLineNumber()以及setLineNumber(int) 只是添加 

对数据行编号的能力,所以可能需要同一个真正的接口对象连接  

PushbackInputStream 有一个字节的后推缓冲区,以便后推读入的上一个字符 InputStream /通常由编译器 

在扫描器中使用,因为 Java 编译器需要它。一般不在自己的代码中使用  



10。2。2 通过 FilterOutputStream 向 OutputStream 里写入数据  



与DataInputStream 对应的是DataOutputStream,后者对各个基本数据类型以及String 对象进行格式化, 

并将其置入一个数据“流”中,以便任何机器上的 DataInputStream 都能正常地读取它们。所有方法都以 

 “wirte”开头,例如writeByte(),writeFloat()等等。  

若想进行一些真正的格式化输出,比如输出到控制台,请使用 PrintStream。利用它可以打印出所有基本数 

据类型以及 String 对象,并可采用一种易于查看的格式。这与DataOutputStream 正好相反,后者的目标是 

将那些数据置入一个数据流中,以便DataInputStream 能够方便地重新构造它们。System。out 静态对象是一 

个PrintStream。  

PrintStream 内两个重要的方法是print()和println() 。它们已进行了覆盖处理,可打印出所有数据类型。 

print()和 println()之间的差异是后者在操作完毕后会自动添加一个新行。  

BufferedOutputStream 属于一种“修改器”,用于指示数据流使用缓冲技术,使自己不必每次都向流内物理 

性地写入数据。通常都应将它应用于文件处理和控制器 IO。  

  

表 10。4 FilterOutputStream 的类型  

  

类 功能 构建器参数/如何使用  

  

DataOutputStream 与 DataInputStream 配合使用,以便采用方便的形式将基本数据类型(int,char,long 

等)写入一个数据流 OutputStream /包含了完整接口,以便我们写入基本数据类型  

PrintStream 用于产生格式化输出。DataOutputStream 控制的是数据的“存储”,而 PrintStream 控制的是 

 “显示” OutputStream ,可选一个布尔参数,指示缓冲区是否与每个新行一同刷新/对于自己的 

OutputStream 对象,应该用“final”将其封闭在内。可能经常都要用到它  



                                                                           287 


…………………………………………………………Page 289……………………………………………………………

BufferedOutputStream 用它避免每次发出数据的时候都要进行物理性的写入,要求它“请先在缓冲区里 

找”。可调用flush(),对缓冲区进行刷新 OutputStream ,可选缓冲区大小/本身并不能提供一个接口,只 

是发出使用缓冲区的要求。需要同一个接口对象连接到一起  



10。3 本身的缺陷:RandomAccessFile  



RandomAccessFile 用于包含了已知长度记录的文件,以便我们能用 seek()从一条记录移至另一条;然后读取 

或修改那些记录。各记录的长度并不一定相同;只要知道它们有多大以及置于文件何处即可。  

首先,我们有点难以相信RandomAccessFile 不属于 InputStream 或者OutputStream 分层结构的一部分。除 

了恰巧实现了DataInput 以及DataOutput (这两者亦由DataInputStream 和 DataOutputStream 实现)接口 

之外,它们与那些分层结构并无什么关系。它甚至没有用到现有 InputStream 或OutputStream 类的功能—— 

采用的是一个完全不相干的类。该类属于全新的设计,含有自己的全部(大多数为固有)方法。之所以要这 

样做,是因为RandomAccessFile 拥有与其他 IO类型完全不同的行为,因为我们可在一个文件里向前或向后 

移动。不管在哪种情况下,它都是独立运作的,作为Object 的一个“直接继承人”使用。  

从根本上说,RandomAccessFile 类似DataInputStream 和 DataOutputStream 的联合使用。其中, 

getFilePointer()用于了解当前在文件的什么地方,seek()用于移至文件内的一个新地点,而 length()用于 

判断文件的最大长度。此外,构建器要求使用另一个自变量(与C 的fopen()完全一样),指出自己只是随 

机读(〃r〃),
返回目录 上一页 下一页 回到顶部 0 0
未阅读完?加入书签已便下次继续阅读!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!