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

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

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