@@ -120,22 +120,122 @@ I/O 流屏蔽了实际的 I/O 设备中处理数据的细节:
120120
121121## Reader和Writer
122122
123+ Java 1.1 对基本的 I/O 流类库做了重大的修改。你初次遇到 ` Reader ` 和 ` Writer ` 时,可能会以为这两个类是用来替代 ` InputStream ` 和 ` OutputStream ` 的,但实际上并不是这样。尽管一些原始的“流”类库已经过时了(如果使用它们,编译器会发出警告),但是 ` InputStream ` 和 ` OutputStream ` 在面向字节 I/O 这方面仍然发挥着极其重要的作用,而 ` Reader ` 和 ` Writer ` 则提供兼容 Unicode 和面向字符 I/O 的功能。另外:
123124
125+ 1 . Java 1.1 往 ` InputStream ` 和 ` OutputStream ` 的继承体系中又添加了一些新类,所以这两个类显然是不会被取代的;
126+
127+ 2 . 有时我们必须把来自“字节”层级结构中的类和来自“字符”层次结构中的类结合起来使用。为了达到这个目的,需要用到“适配器(adapter)类”:` InputStreamReader ` 可以把 ` InputStream ` 转换为 ` Reader ` ,而 ` OutputStreamWriter ` 可以把 ` OutputStream ` 转换为 ` Writer ` 。
128+
129+ 设计 ` Reader ` 和 ` Writer ` 继承体系主要是为了国际化。老的 I/O 流继承体系仅支持 8 比特的字节流,并且不能很好地处理 16 比特的 Unicode 字符。由于 Unicode 用于字符国际化(Java 本身的 ` char ` 也是 16 比特的 Unicode),所以添加 ` Reader ` 和 ` Writer ` 继承体系就是为了让所有的 I/O 操作都支持 Unicode。另外,新类库的设计使得它的操作比旧类库要快。
130+
131+ ### 数据的来源和去处
132+
133+ 几乎所有原始的 Java I/O 流类都有相应的 ` Reader ` 和 ` Writer ` 类来提供原生的 Unicode 操作。但是在某些场合,面向字节的 ` InputStream ` 和 ` OutputStream ` 才是正确的解决方案。特别是 ` java.util.zip ` 类库就是面向字节而不是面向字符的。因此,最明智的做法是尽量** 尝试** 使用 ` Reader ` 和 ` Writer ` ,一旦代码没法成功编译,你就会发现此时应该使用面向字节的类库了。
134+
135+ 下表展示了在两个继承体系中,信息的来源和去处(即数据物理上来自哪里又去向哪里)之间的对应关系:
136+
137+ | 来源与去处:Java 1.0 类 | 相应的 Java 1.1 类 |
138+ | :-------------------: | :--------------: |
139+ | ` InputStream ` | ` Reader ` <br /> 适配器:` InputStreamReader ` |
140+ | ` OutputStream ` | ` Writer ` <br /> 适配器:` OutputStreamWriter ` |
141+ | ` FileInputStream ` | ` FileReader ` |
142+ | ` FileOutputStream ` | ` FileWriter ` |
143+ | ` StringBufferInputStream ` (已弃用) | ` StringReader ` |
144+ | (无相应的类) | ` StringWriter ` |
145+ | ` ByteArrayInputStream ` | ` CharArrayReader ` |
146+ | ` ByteArrayOutputStream ` | ` CharArrayWriter ` |
147+ | ` PipedInputStream ` | ` PipedReader ` |
148+ | ` PipedOutputStream ` | ` PipedWriter ` |
149+
150+ 总的来说,这两个不同的继承体系中的接口即便不能说完全相同,但也是非常相似的。
151+
152+ ### 更改流的行为
153+
154+ 对于 ` InputStream ` 和 ` OutputStream ` 来说,我们会使用 ` FilterInputStream ` 和 ` FilterOutputStream ` 的装饰器子类来修改“流”以满足特殊需要。` Reader ` 和 ` Writer ` 的类继承体系沿用了相同的思想——但是并不完全相同。
155+
156+ 在下表中,左右之间对应关系的近似程度现比上一个表格更加粗略一些。造成这种差别的原因是类的组织形式不同,` BufferedOutputStream ` 是 ` FilterOutputStream ` 的子类,但 ` BufferedWriter ` 却不是 ` FilterWriter ` 的子类(尽管 ` FilterWriter ` 是抽象类,但却没有任何子类,把它放在表格里只是占个位置,不然你可能奇怪 ` FilterWriter ` 上哪去了)。然而,这些类的接口却又十分相似。
157+
158+ | 过滤器:Java 1.0 类 | 相应 Java 1.1 类 |
159+ | :--------------- | :-------------- |
160+ | ` FilterInputStream ` | ` FilterReader ` |
161+ | ` FilterOutputStream ` | ` FilterWriter ` (抽象类,没有子类) |
162+ | ` BufferedInputStream ` | ` BufferedReader ` (也有 ` readLine() ` ) |
163+ | ` BufferedOutputStream ` | ` BufferedWriter ` |
164+ | ` DataInputStream ` | 使用 ` DataInputStream ` ( 如果必须用到 ` readLine() ` ,那你就得使用 ` BufferedReader ` 。否则,一般情况下就用 ` DataInputStream ` |
165+ | ` PrintStream ` | ` PrintWriter ` |
166+ | ` LineNumberInputStream ` | ` LineNumberReader ` |
167+ | ` StreamTokenizer ` | ` StreamTokenizer ` (使用具有 ` Reader ` 参数的构造器) |
168+ | ` PushbackInputStream ` | ` PushbackReader ` |
169+
170+ 有一条限制需要明确:一旦要使用 ` readLine() ` ,我们就不应该用 ` DataInputStream ` (否则,编译时会得到使用了过时方法的警告),而应该使用 ` BufferedReader ` 。除了这种情况之外的情形中,` DataInputStream ` 仍是 I/O 类库的首选成员。
171+
172+ 为了使用时更容易过渡到 ` PrintWriter ` ,它提供了一个既能接受 ` Writer ` 对象又能接受任何 ` OutputStream ` 对象的构造器。` PrintWriter ` 的格式化接口实际上与 ` PrintStream ` 相同。
173+
174+ Java 5 添加了几种 ` PrintWriter ` 构造器,以便在将输出写入时简化文件的创建过程,你马上就会见到它们。
175+
176+ 其中一种 ` PrintWriter ` 构造器还有一个执行** 自动 flush** [ ^ 2 ] 的选项。如果构造器设置了该选项,就会在每个 ` println() ` 调用之后,自动执行 flush。
177+
178+ ### 未发生改变的类
179+
180+ 有一些类在 Java 1.0 和 Java 1.1 之间未做改变。
181+
182+ | 以下这些 Java 1.0 类在 Java 1.1 中没有相应类 |
183+ | --- |
184+ | ` DataOutputStream ` |
185+ | ` File ` |
186+ | ` RandomAccessFile ` |
187+ | ` SequenceInputStream ` |
188+
189+ 特别是 ` DataOutputStream ` ,在使用时没有任何变化;因此如果想以可传输的格式存储和检索数据,请用 ` InputStream ` 和 ` OutputStream ` 继承体系。
124190
125191<!-- Off By Itself: RandomAccessFile -->
126192## RandomAccessFile类
127193
128194
195+
129196<!-- Typical Uses of I/O Streams -->
130197## IO流典型用途
131198
132199
200+
201+ ### 缓冲输入文件
202+
203+
204+
205+ ### 从内存输入
206+
207+
208+
209+ ### 格式化内存输入
210+
211+
212+
213+ ### 基本文件的输出
214+
215+
216+
217+ ### 文本文件输出快捷方式
218+
219+
220+
221+ ### 存储和恢复数据
222+
223+
224+
225+ ### 读写随机访问文件
226+
227+
228+
133229<!-- Summary -->
134230## 本章小结
135231
232+
233+
136234[ ^ 1 ] : 很难说这就是一个很好的设计选择,尤其是与其它编程语言中简单的 I/O 类库相比较。但它确实是如此选择的一个正当理由。
137235
138- [ ^ 2 ] : XML 是另一种方式,可以解决在不同计算平台之间移动数据,而不依赖于所有平台上都有 Java 这一问题。XML 将在[ 附录:对象序列化] ( ./Appendix-Object-Serialization.md ) 一章中进行介绍。
236+ [ ^ 2 ] : 译者注:“flush” 直译是“清空”,意思是把缓冲中的数据清空,输送到对应的目的地(如文件和屏幕)。
237+
238+ [ ^ 3 ] : XML 是另一种方式,可以解决在不同计算平台之间移动数据,而不依赖于所有平台上都有 Java 这一问题。XML 将在[ 附录:对象序列化] ( ./Appendix-Object-Serialization.md ) 一章中进行介绍。
139239
140240<!-- 分页 -->
141241
0 commit comments