⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chapter10.htm

📁 Thinking In Java的中文版。Java学习的经典教程。
💻 HTM
📖 第 1 页 / 共 5 页
字号:
<br>
发起&接收:Java 1.0类 对应的Java 1.1类<br>
<br>
474页表中内容略<br>
<br>
我们发现即使不完全一致,但旧库组件中的接口与新接口通常也是类似的。<br>
<br>
10.7.2 修改数据流的行为<br>
在Java 1.0中,数据流通过FilterInputStream和FilterOutputStream的“装饰器”(Decorator)子类适应特定的需求。Java 
1.1的IO流沿用了这一思想,但没有继续采用所有装饰器都从相同“filter”(过滤器)基础类中衍生这一做法。若通过观察类的层次结构来理解它,这可能令人出现少许的困惑。<br>
在下面这张表格中,对应关系比上一张表要粗糙一些。之所以会出现这个差别,是由类的组织造成的:尽管BufferedOutputStream是FilterOutputStream的一个子类,但是BufferedWriter并不是FilterWriter的子类(对后者来说,尽管它是一个抽象类,但没有自己的子类或者近似子类的东西,也没有一个“占位符”可用,所以不必费心地寻找)。然而,两个类的接口是非常相似的,而且不管在什么情况下,显然应该尽可能地使用新版本,而不应考虑旧版本(也就是说,除非在一些类中必须生成一个Stream,不可生成Reader或者Writer)。<br>
<br>
过滤器:Java 1.0类 对应的Java 1.1类<br>
<br>
FilterInputStream FilterReader<br>
FilterOutputStream FilterWriter(没有子类的抽象类)<br>
BufferedInputStream BufferedReader(也有readLine())<br>
BufferedOutputStream BufferedWriter<br>
DataInputStream 使用DataInputStream(除非要使用readLine(),那时需要使用一个BufferedReader)<br>
PrintStream PrintWriter<br>
LineNumberInputStream LineNumberReader<br>
StreamTokenizer StreamTokenizer(用构建器取代Reader)<br>
PushBackInputStream PushBackReader<br>
<br>
有一条规律是显然的:若想使用readLine(),就不要再用一个DataInputStream来实现(否则会在编译期得到一条出错消息),而应使用一个BufferedReader。但除这种情况以外,DataInputStream仍是Java 
1.1 IO库的“首选”成员。<br>
为了将向PrintWriter的过渡变得更加自然,它提供了能采用任何OutputStream对象的构建器。PrintWriter提供的格式化支持没有PrintStream那么多;但接口几乎是相同的。<br>
<br>
10.7.3 未改变的类<br>
显然,Java库的设计人员觉得以前的一些类毫无问题,所以没有对它们作任何修改,可象以前那样继续使用它们:<br>
<br>
没有对应Java 1.1类的Java 1.0类<br>
<br>
DataOutputStream<br>
File<br>
RandomAccessFile<br>
SequenceInputStream<br>
<br>
特别未加改动的是DataOutputStream,所以为了用一种可转移的格式保存和获取数据,必须沿用InputStream和OutputStream层次结构。<br>
<br>
10.7.4 一个例子<br>
为体验新类的效果,下面让我们看看如何修改IOStreamDemo.java示例的相应区域,以便使用Reader和Writer类:<br>
<br>
476-478页程序<br>
<br>
大家一般看见的是转换过程非常直观,代码看起来也颇相似。但这些都不是重要的区别。最重要的是,由于随机访问文件已经改变,所以第6节未再重复。<br>
第1节收缩了一点儿,因为假如要做的全部事情就是读取行输入,那么只需要将一个FileReader封装到BufferedReader之内即可。第1b节展示了封装System.in,以便读取控制台输入的新方法。这里的代码量增多了一些,因为System.in是一个DataInputStream,而且BufferedReader需要一个Reader参数,所以要用InputStreamReader来进行转换。<br>
在2节,可以看到如果有一个字串,而且想从中读取数据,只需用一个StringReader替换StringBufferInputStream,剩下的代码是完全相同的。<br>
第3节揭示了新IO流库设计中的一个错误。如果有一个字串,而且想从中读取数据,那么不能再以任何形式使用StringBufferInputStream。若编译一个涉及StringBufferInputStream的代码,会得到一条“反对”消息,告诉我们不要用它。此时最好换用一个StringReader。但是,假如要象第3节这样进行格式化的内存输入,就必须使用DataInputStream——没有什么“DataReader”可以代替它——而DataInputStream很不幸地要求用到一个InputStream参数。所以我们没有选择的余地,只好使用编译器不赞成的StringBufferInputStream类。编译器同样会发出反对信息,但我们对此束手无策(注释②)。<br>
StringReader替换StringBufferInputStream,剩下的代码是完全相同的。<br>
<br>
②:到你现在正式使用的时候,这个错误可能已经修正。<br>
<br>
第4节明显是从老式数据流到新数据流的一个直接转换,没有需要特别指出的。在第5节中,我们被强迫使用所有的老式数据流,因为DataOutputStream和DataInputStream要求用到它们,而且没有可供替换的东西。然而,编译期间不会产生任何“反对”信息。若不赞成一种数据流,通常是由于它的构建器产生了一条反对消息,禁止我们使用整个类。但在DataInputStream的情况下,只有readLine()是不赞成使用的,因为我们最好为readLine()使用一个BufferedReader(但为其他所有格式化输入都使用一个DataInputStream)。<br>
若比较第5节和IOStreamDemo.java中的那一小节,会注意到在这个版本中,数据是在文本之前写入的。那是由于Java 
1.1本身存在一个错误,如下述代码所示:<br>
<br>
479-480页程序<br>
<br>
看起来,我们在对一个writeBytes()的调用之后写入的任何东西都不是能够恢复的。这是一个十分有限的错误,希望在你读到本书的时候已获得改正。为检测是否改正,请运行上述程序。若没有得到一个违例,而且值都能正确打印出来,就表明已经改正。<br>
<br>
10.7.5 重导向标准IO<br>
Java 1.1在System类中添加了特殊的方法,允许我们重新定向标准输入、输出以及错误IO流。此时要用到下述简单的静态方法调用:<br>
setIn(InputStream)<br>
setOut(PrintStream)<br>
setErr(PrintStream)<br>
如果突然要在屏幕上生成大量输出,而且滚动的速度快于人们的阅读速度,输出的重定向就显得特别有用。在一个命令行程序中,如果想重复测试一个特定的用户输入序列,输入的重定向也显得特别有价值。下面这个简单的例子展示了这些方法的使用:<br>
<br>
481页程序<br>
<br>
这个程序的作用是将标准输入同一个文件连接起来,并将标准输出和错误重定向至另一个文件。<br>
这是不可避免会遇到“反对”消息的另一个例子。用-deprecation标志编译时得到的消息如下:<br>
<br>
Note:The constructor java.io.PrintStream(java.io.OutputStream) has been deprecated.<br>
注意:不推荐使用构建器java.io.PrintStream(java.io.OutputStream)。<br>
<br>
然而,无论System.setOut()还是System.setErr()都要求用一个PrintStream作为参数使用,所以必须调用PrintStream构建器。所以大家可能会觉得奇怪,既然Java 
1.1通过反对构建器而反对了整个PrintStream,为什么库的设计人员在添加这个反对的同时,依然为System添加了新方法,且指明要求用PrintStream,而不是用PrintWriter呢?毕竟,后者是一个崭新和首选的替换措施呀?这真令人费解。<br>
<br>
10.8 压缩<br>
Java 1.1也添加一个类,用以支持对压缩格式的数据流的读写。它们封装到现成的IO类中,以提供压缩功能。<br>
此时Java 1.1的一个问题显得非常突出:它们不是从新的Reader和Writer类衍生出来的,而是属于InputStream和OutputStream层次结构的一部分。所以有时不得不混合使用两种类型的数据流(注意可用InputStreamReader和OutputStreamWriter在不同的类型间方便地进行转换)。<br>
<br>
Java 1.1压缩类 功能<br>
<br>
CheckedInputStream GetCheckSum()为任何InputStream产生校验和(不仅是解压)<br>
CheckedOutputStream GetCheckSum()为任何OutputStream产生校验和(不仅是解压)<br>
DeflaterOutputStream 用于压缩类的基础类<br>
ZipOutputStream 一个DeflaterOutputStream,将数据压缩成Zip文件格式<br>
GZIPOutputStream 一个DeflaterOutputStream,将数据压缩成GZIP文件格式<br>
InflaterInputStream 用于解压类的基础类<br>
ZipInputStream 一个DeflaterInputStream,解压用Zip文件格式保存的数据<br>
GZIPInputStream 一个DeflaterInputStream,解压用GZIP文件格式保存的数据<br>
<br>
尽管存在许多种压缩算法,但是Zip和GZIP可能最常用的。所以能够很方便地用多种现成的工具来读写这些格式的压缩数据。<br>
<br>
10.8.1 用GZIP进行简单压缩<br>
GZIP接口非常简单,所以如果只有单个数据流需要压缩(而不是一系列不同的数据),那么它就可能是最适当选择。下面是对单个文件进行压缩的例子:<br>
<br>
483-484页程序<br>
<br>
压缩类的用法非常直观——只需将输出流封装到一个GZIPOutputStream或者ZipOutputStream内,并将输入流封装到GZIPInputStream或者ZipInputStream内即可。剩余的全部操作就是标准的IO读写。然而,这是一个很典型的例子,我们不得不混合使用新旧IO流:数据的输入使用Reader类,而GZIPOutputStream的构建器只能接收一个OutputStream对象,不能接收Writer对象。<br>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -