返回介绍

10.7.4 一个例子

发布于 2024-10-15 23:56:24 字数 5434 浏览 0 评论 0 收藏 0

为体验新类的效果,下面让我们看看如何修改 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");
      }

      // 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]);
    } 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 pi\n");
    out.writeBytes("This is pi/2:\n");
    out.writeDouble(3.14159/2);
    out.close();

    DataInputStream in =
      new DataInputStream(
        new BufferedInputStream(
          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() 的调用之后写入的任何东西都不是能够恢复的。这是一个十分有限的错误,希望在你读到本书的时候已获得改正。为检测是否改正,请运行上述程序。若没有得到一个违例,而且值都能正确打印出来,就表明已经改正。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文