為體驗新類的效果,下面讓我們看看如何修改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()的調用之後寫入的任何東西都不是能夠恢復的。這是一個十分有限的錯誤,希望在你讀到本書的時候已獲得改正。為檢測是否改正,請運行上述程序。若沒有得到一個違例,而且值都能正確打印出來,就表明已經改正。