按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
缺点——需要为额外的灵活性付出代价。
之所以在Java 1。1 里添加了Reader 和 Writer 层次,最重要的原因便是国际化的需求。老式 IO流层次结构
只支持8 位字节流,不能很好地控制 16 位Unicode 字符。由于Unicode 主要面向的是国际化支持(Java 内
含的 char 是 16 位的Unicode),所以添加了Reader 和 Writer 层次,以提供对所有 IO 操作中的Unicode 的
支持。除此之外,新库也对速度进行了优化,可比旧库更快地运行。
与本书其他地方一样,我会试着提供对类的一个概述,但假定你会利用联机文档搞定所有的细节,比如方法
的详尽列表等。
10。7。1 数据的发起与接收
Java 1。0 的几乎所有 IO流类都有对应的Java 1。1 类,用于提供内建的Unicode 管理。似乎最容易的事情就
是“全部使用新类,再也不要用旧的”,但实际情况并没有这么简单。有些时候,由于受到库设计的一些限
制,我们不得不使用Java 1。0 的 IO流类。特别要指出的是,在旧流库的基础上新加了 java。util。zip 库,
它们依赖旧的流组件。所以最明智的做法是“尝试性”地使用 Reader 和 Writer 类。若代码不能通过编译,
便知道必须换回老式库。
下面这张表格分旧库与新库分别总结了信息发起与接收之间的对应关系。
发起&接收: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〃);
}
}
} ///:~
大家一般看见的是转换