原文链接
原文:
Buffered Streams
Most of the examples we’ve seen so far use unbuffered I/O. This means each read or write request is handled directly by the underlying OS. This can make a program much less efficient, since each such request often triggers disk access, network activity, or some other operation that is relatively expensive.
To reduce this kind of overhead, the Java platform implements buffered I/O streams. Buffered input streams read data from a memory area known as a buffer; the native input API is called only when the buffer is empty. Similarly, buffered output streams write data to a buffer, and the native output API is called only when the buffer is full.
A program can convert an unbuffered stream into a buffered stream using the wrapping idiom we’ve used several times now, where the unbuffered stream object is passed to the constructor for a buffered stream class. Here’s how you might modify the constructor invocations in the CopyCharacters example to use buffered I/O:
inputStream = new BufferedReader(new FileReader(“xanadu.txt”));
outputStream = new BufferedWriter(new FileWriter(“characteroutput.txt”));
There are four buffered stream classes used to wrap unbuffered streams: BufferedInputStream and BufferedOutputStream create buffered byte streams, while BufferedReader and BufferedWriter create buffered character streams.
Flushing Buffered Streams
It often makes sense to write out a buffer at critical points, without waiting for it to fill. This is known as flushing the buffer.
Some buffered output classes support autoflush, specified by an optional constructor argument. When autoflush is enabled, certain key events cause the buffer to be flushed. For example, an autoflush PrintWriter object flushes the buffer on every invocation of println or format. See Formatting for more on these methods.
To flush a stream manually, invoke its flush method. The flush method is valid on any output stream, but has no effect unless the stream is buffered.
译文:
缓冲流
目前为止我们看到过的大多数例子使用的都是非缓冲I/O。这意味着每个读写操作请求都由底层的系统直接处理。这样会让一个程序效率低下,因为每个这样的请求经常会出发磁盘访问,网络活动,或者一些其他的相对昂贵的直接性操作。
为了减少这种经常性的支出,java平台实现了缓冲I/O流。缓冲输入流从内存中被称为缓冲的区域读取数据,当缓冲区是空的时,本地的输入API才会被调用。同样地,缓冲输出流从缓冲中写入数据,当缓冲满时,本地输出API才会被调用。
一个程序可以用现在我们用过几次的封装语句,将一个不是缓冲的流转换成一个缓冲流,其中的非缓冲流对象被传递给一个缓冲流类的构造方法。
下面是一个例子,告诉你如何修改名叫CopyCharacters的例子的构造方法调用来使用缓冲I/O。
有四个缓冲流类被用来封装非缓冲流:BufferredInputStream和BufferedOutputStream创建了缓冲字节流,而BufferedReader和BufferedWriter创建了缓冲字符流。
清空缓冲流
在临界点写出一个缓冲区是有意义的,而不是等待他填满时。这被称作是清空缓冲。
很多缓冲输出类支持自动清空,由一个可选的的构造方法指定。当自动清空不可用时,某个关键事件可以使缓冲被清空。举个例子,一个自动清空PrintWriter的对象清在每个调用换行输出或者格式化的方法时清空了缓冲。可以看“格式化”这一章了解更多的相关方法。
为了能够手动清空一个流,调用其他的flush方法。flush方法是在任何输出流上有效的,但如果流是缓冲的,就没有效果。