友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!
富士康小说网 返回本书目录 加入书签 我的书架 我的书签 TXT全本下载 『收藏到我的浏览器』

Java编程思想第4版[中文版](PDF格式)-第56部分

快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部! 如果本书没有阅读完,想下次继续接着阅读,可使用上方 "收藏到我的浏览器" 功能 和 "加入书签" 功能!



  

发起&接收:Java 1。0 类 对应的 Java 1。1 类  

  



Sources & Sinks:     Corresponding Java 1。1 class  

Java 1。0 class  



                                                                            305 


…………………………………………………………Page 307……………………………………………………………

I n p u t S t r e a m     R e a d e r    

                          converter: InputStreamReader  



O u t p u t S t r e a m   W r i t e r    

                          converter: OutputStreamWriter  



F i l e I n p u t S t r e a m   F i l e R e a d e r   



F i l e O u t p u t S t r e a m   F i l e W r i t e r   



StringBufferInputStream S t r i n g R e a d e r  



(no corresponding class) S t r i n g W r i t e r  



ByteArrayInputStream  C h a r A r r a y R e a d e r  



ByteArrayOutputStream  C h a r A r r a y W r i t e r  



P i p e d I n p u t S t r e a m   P i p e d R e a d e r   



P i p e d O u t p u t S t r e a m   P i p e d W r i t e r   



我们发现即使不完全一致,但旧库组件中的接口与新接口通常也是类似的。  



10。7。2 修改数据流的行为  



在Java 1。0 中,数据流通过FilterInputStream 和FilterOutputStream 的“装饰器”(Decorator)子类适 

应特定的需求。Java 1。1 的 IO流沿用了这一思想,但没有继续采用所有装饰器都从相同“filter”(过滤 

器)基础类中衍生这一做法。若通过观察类的层次结构来理解它,这可能令人出现少许的困惑。  

在下面这张表格中,对应关系比上一张表要粗糙一些。之所以会出现这个差别,是由类的组织造成的:尽管 

BufferedOutputStream 是 FilterOutputStream 的一个子类,但是BufferedWriter 并不是FilterWriter 的 

子类(对后者来说,尽管它是一个抽象类,但没有自己的子类或者近似子类的东西,也没有一个“占位符” 

可用,所以不必费心地寻找)。然而,两个类的接口是非常相似的,而且不管在什么情况下,显然应该尽可 

能地使用新版本,而不应考虑旧版本(也就是说,除非在一些类中必须生成一个Stream,不可生成 Reader 

或者Writer)。  

  

过滤器:Java 1。0 类 对应的 Java 1。1 类  

  

FilterInputStream FilterReader  

FilterOutputStream FilterWriter (没有子类的抽象类)  

BufferedInputStream BufferedReader (也有readLine())  

BufferedOutputStream BufferedWriter  

DataInputStream 使用DataInputStream (除非要使用readLine(),那时需要使用一个BufferedReader)  

PrintStream PrintWriter  

LineNumberInputStream LineNumberReader  

StreamTokenizer StreamTokenizer (用构建器取代Reader)  

PushBackInputStream PushBackReader  

  

有一条规律是显然的:若想使用readLine(),就不要再用一个DataInputStream 来实现(否则会在编译期得 

到一条出错消息),而应使用一个 BufferedReader。但除这种情况以外,DataInputStream 仍是Java 1。1  

IO库的“首选”成员。  

为了将向PrintWriter 的过渡变得更加自然,它提供了能采用任何OutputStream 对象的构建器。 

PrintWriter 提供的格式化支持没有 PrintStream 那么多;但接口几乎是相同的。  



10。7。3 未改变的类  



显然,Java 库的设计人员觉得以前的一些类毫无问题,所以没有对它们作任何修改,可象以前那样继续使用 

它们:  

  

没有对应Java 1。1 类的Java 1。0 类  



                                                                                               306 


…………………………………………………………Page 308……………………………………………………………

  

DataOutputStream  

File  

RandomAccessFile  

SequenceInputStream  

  

特别未加改动的是 DataOutputStream,所以为了用一种可转移的格式保存和获取数据,必须沿用 

InputStream和 OutputStream 层次结构。  



10。7。4 一个例子  



为体验新类的效果,下面让我们看看如何修改 IOStreamDemo。java示例的相应区域,以便使用Reader 和 

Writer 类:  

  

//: NewIODemo。java  

// Java 1。1 IO typical usage  

import java。io。*;  

  

public class NewIODemo  {  

  public static void main(String'' args) {  

    try {  

      // 1。 Reading input by lines:  

      BufferedReader in =  

        new BufferedReader(  

          new FileReader(args'0'));  

      String s; s2 = new String();  

      while((s = in。readLine())!= null)  

        s2 += s + 〃n〃;  

      in。close();  

  

      // 1b。 Reading standard input:  

      BufferedReader stdin =  

        new BufferedReader(  

          new InputStreamReader(System。in));        

      System。out。print(〃Enter a line:〃);  

      System。out。println(stdin。readLine());  

  

      // 2。 Input from memory  

      StringReader in2 = new StringReader(s2);  

      int c;  

      while((c = in2。read()) != …1)  

        System。out。print((char)c);  

  

      // 3。 Formatted memory input  

      try {  

        DataInputStream in3 =  

          new DataInputStream(  

            // Oops: must use deprecated class:  

            new StringBufferInputStream(s2));  

        while(true)  

          System。out。print((char)in3。readByte());  

      } catch(EOFException e) {  

        System。out。println(〃End of stream〃);  



                                                                                          307 


…………………………………………………………Page 309……………………………………………………………

      }  

  

      // 4。 Line numbering & file output  

      try {  

        LineNumberReader li =  

          new LineNumberReader(  

            new StringReader(s2));  

        BufferedReader in4 =  

          new BufferedReader(li);  

        PrintWriter out1 =  

          new PrintWriter(  

            new BufferedWriter(  

              new FileWriter(〃IODemo。out〃)));  

        while((s = in4。readLine()) != null )  

          out1。println(  

            〃Line 〃 + li。getLineNumber() + s);  

        out1。close();  

      } catch(EOFException e) {  

        System。out。println(〃End of stream〃);  

      }  

  

      // 5。 Storing & recovering data  

      try {  

        DataOutputStream out2 =  

          new DataOutputStream(  

            new BufferedOutputStream(  

              new FileOutputStream(〃Data。txt〃)));  

        out2。writeDouble(3。14159);  

        out2。writeBytes(〃That was pi〃);  

        out2。close();  

        DataInputStream in5 =  

          new DataInputStream(  

            new BufferedInputStream(  

              new FileInputStream(〃Data。txt〃)));  

        BufferedReader in5br =  

          new BufferedReader(  

            new InputStreamReader(in5));  

        // Must use DataInputStream for data:  

        System。out。println(in5。readDouble());  

        // Can now use the 〃proper〃 readLine():  

        System。out。println(in5br。readLine());  

      } catch(EOFException e) {  

        System。out。println(〃End of stream〃);  

      }  

  

      // 6。 Reading and writing random access  

      // files is the same as before。  

      // (not repeated here)  

  

    } catch(FileNotFoundException e) {  

      System。out。println(  

        〃File Not Found:〃 + args'1');  



                                                                                          308 


…………………………………………………………Page 310……………………………………………………………

    } catch(IOException e) {  

      System。out。println(〃IO Exception〃);  

    }  

  }  

} ///:~  

  

大家一般看见的是转换过程非常直观,代码看起来也颇相似。但这些都不是重要的区别。最重要的是,由于 

随机访问文件已经改变,所以第6 节未再重复。  

第 1 节收缩了一点儿,因为假如要做的全部事情就是读取行输入,那么只需要将一个 FileReader 封装到 

BufferedReader 之内即可。第 1b 节展示了封装System。in,以便读取控制台输入的新方法。这里的代码量增 

多了一些,因为System。in 是一个DataInputStream,而且BufferedReader 需要一个Reader 参数,所以要 

用 InputStreamReader来进行转换。  

在 2 节,可以看到如果有一个字串,而且想从中读取数据,只需用一个StringReader 替换 

StringBufferInputStream,剩下的代码是完全相同的。  

第 3 节揭示了新 IO流库设计中的一个错误。如果有一个字串,而且想从中读取数据,那么不能再以任何形式 

使用StringBufferInputStream。若编译一个涉及StringBufferInputStream 的代码,会得到一条“反对” 

消息,告诉我们不要用它。此时最好换用一个 StringReader。但是,假如要象第3 节这样进行格式化的内存 

输入,就必须使用 DataInputStream——没有什么“DataReader”可以代替它——而DataInputStream 很不 

幸地要求用到一个 InputStream 参数。所以我们没有选择的余地,只好使用编译器不赞成的 

StringBufferInputStream 类。编译器同样会发出反对信息,但我们对此束手无策(注释②)。  

StringReader 替换StringBufferInputStream,剩下的代码是完全相同的。  

  

②:到你现在正式使用的时候,这个错误可能已经修正。  

  

第4 节明显是从老式数据流到新数据流的一个直接转换,没有需要特别指出的。在第 5 节中,我们被强迫使 

用所有的老式数据流,因为DataOutputStream 和 DataInputStream 要求用到它们,而且没有可供替换的东 

西。然而,编译期间不会产生任何“反对”信息。若不赞成一种数据流,通常是由于它的构建器产生了一条 

反对消息,禁止我们使用整个类。但在DataInputStream 的情况下,只有readLine()是不赞成使用的,因为 

我们最好为 readLine()使用一个 BufferedReader (但为其他所有格式化输入都使用一个 

DataInputStream)。  

若比较第5 节和 IOStreamDemo。java 中的那一小节,会注意到在这个版本中,数据是在文本之前写入的。那 

是由于Java 1。1 本身存在一个错误,如下述代码所示:  

  

//: IOBug。java  

// Java 1。1 (and higher?) IO Bug  

import java。io。*;  

  

public class IOBug {  

  public static void main(String'' args)   

  throws Exception {  

    DataOutputStream out =  

      new DataOutputStream(  

        new BufferedOutputStream(   

          new FileOutputStream(〃Data。txt〃)));  

    out。writeDouble(3。14159);  

    out。writeBytes(〃That was the value of pin〃);  

    out。writeBytes(〃This is pi/2:n〃);  

    out。writeDouble(3。14159/2);  

    out。close();  

    DataInputStream in =  

      new DataInputStream(  

        new BufferedInputStream(  



                                                                                         309 


…………………………………………………………Page 311……………………………………………………………

          new FileInputStream(〃Data。txt〃)));  

    BufferedReader inbr =  

      new BufferedReader(  

        new InputStreamReader(in));  

    // The doubles written BEFORE the line of text  

    // read back correctly:  

    System。out。println(in。readDouble());  

    // Read the lines of text:  

    System。out。println(inbr。readLine());  

    System。out。println(inbr。readLine());  

    // Trying to read the doubles after the line  

    // produces an end…of…file exception:  

    System。out。println(in。readDouble());  

  }  

} ///:~  

  

看起来,我们在对一个 writeBytes()的调用之后写入的任何东西都不是能够恢复的。这是一个十分有限的错 

误,希望在你读到本书的时候已获得改正。为检测是否改正,请运行上述程序。若没有得到一个违例,而且 

值都能正确打印出来,就表明已经改正。  



10。7。5 重导向标准 IO  



Java 1。1 在System 类中添加了特殊的方法,允许我们重新定向标准输入、输出以及错误 IO流。此时要用到 

下述简单的静态方法调用:  

setIn(InputStream)  

setOut(PrintStream)  

setErr(PrintStream)  

如果突然要在屏幕上生成大量输出,而且滚动的速度快于人们的阅读速度,输出的重定向就显得特别有用。 

在一个命令行程序中,如果想重复测试一个特定的用户输入序列,输入的重定向也显得特别有价值。下面这 

个简单的例子展示了这些方法的使用:  

  

//: Redirecting。java  

// Demonstrates the use of redirection for   

// standard IO in Java 1。1  

import java。io。*;  

  

class Redirecting {  

  public static void main(String'' args) {  

    try {  

      BufferedInputStream in =   

        new BufferedInputStream(  

          new FileInputStream(  

            〃Redirecting。java〃));  

      // Produces deprecation message:  

      PrintStream out =  

        new PrintStream(  

          new BufferedOutputStream(  

            new FileOutputStream(〃test。out〃)));  

      System。setIn(in);  

      System。setOut(out);  

      System。setErr(out);  

      BufferedReader br =   

        new BufferedReader(  



                                                                                          310 


…………………………………………………………Page 312……………………………………………………………

          new InputStreamReader(System。in));  

      String s;  

      while((s = br。readLine()) != null)  

        System。out。println(s);  

      out。close(); // Remember this!  

    } catch(IOException e) {  

      e。printStackTrace();  

    }  

  }  

} ///:~  

  

这个程序的作用是将标准输入同一个文件连接起来,并将标准输出和错误重定向至另一个文件。  

这是不可避免会遇到“反对”消息的另一个例子。用…deprecation 标志编译时得到的消息如下:  

  

Note:The constructor java。io。PrintStream(java。io。OutputStream) has been deprecated。  

注意:不推荐使用构建器java。io。PrintStream (java。io。OutputStream)。  

  

然而,无论 System。setOut()还是System。setErr()都要求用一个 PrintStream 作为参数使用,所以必须调用 

PrintStream 构建器。所以大家可能会觉得奇怪,既然 Java 1。1 通过反对构建器而反对了整个 

PrintStream,为什么库的设计人员在添加这个反对的同时,依然为System 添加了新方法,且指明要求用 

PrintStream,而不是用 PrintWriter 呢?毕竟,后者是一个崭新和首选的替换措施呀?这真令人费解。  



10。8 压缩  



Java 1。1 也添加一个类,用以支持对压缩格式的数据流的读写。它们封装到现成的 IO类中,以提供压缩功 

能。  

此时Java 1。1 的一个问题显得非常突出:它们不是从新的Reader 和Writer 类衍生出来的,而是属于 

InputStream和 OutputStream 层次结构的一部分。所以有时不得不混合使用两种类型的数据流(注意可用 

InputStreamReader和OutputStreamWriter 在不同的类型间方便地进行转换)。  

  

Java 1。1 压缩类 功能  

  

CheckedInputStream GetCheckSum()为任何 InputStream 产生校验和(不仅是解压)  

CheckedOutputStream GetCheckSum()为任何OutputStream 产生校验和(不仅是解压)  

DeflaterOutputStream 用于压缩类的基础类  

ZipOutputStream 一个DeflaterOutputStream,将数据压缩成Zip 文件格式  

GZIPOutputStream 一个DeflaterOutputStream,将数据压缩成GZIP 文件格式  

InflaterInputStream 用于解压类的基础类  

ZipInputStream 一个 DeflaterInputStream,解压用Zip 文件格式保存的数据  

GZIPInputStream 一个DeflaterInputStream,解压用GZIP 文件格式保存的数据  

  

尽管存在许多种压缩算法,但是Zip 和 GZIP 可能最常用的。所以能够很方便地用多种现成的工具来读写这些 

格式的压缩数据。  



10。8。1 用 GZIP 进行简单压缩  



GZIP 接口非常简单,所以如果只有单个数据流需要压缩(而不是一系列不同的数据),那么它就可能是最适 

当选择。下面是对单个文件进行压缩的例子:  

  

//: GZIPpress。java  

// Uses Java 1。1 GZIP pression to press  

// a file whose name is passed on the mand  

// line。  



                                                                                        311 


…………………………………………………………Page 313……………………………………………………………

import java。io。*;  

import java。util。zip。*;  

  

public class GZIPpress {  

  public static void main(String'' args) {  

    try {  

      BufferedReader in =  

        new BufferedReader(  

          new FileReader(args'0'));  

      BufferedOutputStream out =  

        new BufferedOutputStream(  

          new GZIPOutputStream(  

            new FileOutputStream(〃test。gz〃)));  

      System。out。println(〃Writing file〃);  

      int c;  

      while((c = in。read()) != …1)  

        out。write(c);  

      in。close();  

      out。close();  

      System
返回目录 上一页 下一页 回到顶部 10 9
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!