制它的数组;也就是说 ,当它导出了 String 且后来调用程序修改了 StringBuffer 的时候。如果没有 发生这样的修改,那么任何不必要的复制都不会被执行。通过支持能够强制适当 的访问控制的字节数组的包装器,新的 I/O 框架以类似的方式解决了这个问题 。
我们可以使用相同的通用机制为需要使用标准流 API 的应用程序提供高效的 数据缓冲和再次读取。我们的示例给出了可替代 ByteArrayOutputStream 类的 类,它能高效地导出对内部缓冲区的只读访问,方法是返回直接读取内部字节数 组的只读 InputStream 。
彻底转变流,第2部分:优化Java内部I/O(2)
时间:2011-06-21 Merlin Hughes
我们来看一下代码。清单 1 中的构造函数分配了初始缓冲区,以存储写到这 个流的数据。为了存储更多的数据,该缓冲区将按需自动地扩展。
清单 1. 不同步的字节数组输出流
package org.merlin.io;
import java.io.*;
/**
* An unsynchronized ByteArrayOutputStream alternative that efficiently
* provides read-only access to the internal byte array with no
* unnecessary copying.
*
* @author Copyright (c) 2002 Merlin Hughes <merlin@merlin.org>
*/
public class BytesOutputStream extends OutputStream {
private static final int DEFAULT_INITIAL_BUFFER_SIZE = 8192;
// internal buffer
private byte[] buffer;
private int index, capacity;
// is the stream closed?
private boolean closed;
// is the buffer shared?
private boolean shared;
public BytesOutputStream () {
this (DEFAULT_INITIAL_BUFFER_SIZE);
}
public BytesOutputStream (int initialBufferSize) {
capacity = initialBufferSize;
buffer = new byte[capacity];
}
清单 2 显示的是写方法。这些方法按需扩展内部缓冲区,然后把新数据复制 进来。在扩展内部缓冲区时,我们使缓冲区的大小增加了一倍再加上存储新数据 所需的容量;这样,为了存储任何所需的数据,缓冲区的容量成指数地增长。为 了提高效率,如果您知道您将写入的数据的预期容量,那么您应该指定相应的初 始缓冲区的大小。 close() 方法只是设置了一个合适的标志。
清单 2. 写方法
public void write (int datum) throws IOException {
if (closed) {
throw new IOException ("Stream closed");
} else {
if (index >= capacity) {
// expand the internal buffer
capacity = capacity * 2 + 1;
byte[] tmp = new byte[capacity];
System.arraycopy (buffer, 0, tmp, 0, index);
buffer = tmp;
// the new buffer is not shared
shared = false;
}
// store the byte
buffer[index ++] = (byte) datum;
}
}
public void write (byte[] data, int offset, int length)
throws IOException {
if (data == null) {
throw new NullPointerException ();
} else if ((offset < 0) || (offset + length > data.length)
|| (length < 0)) {
throw new IndexOutOfBoundsException ();
} else if (closed) {
throw new IOException ("Stream closed");
} else {
if (index + length > capacity) {
// expand the internal buffer
capacity = capacity * 2 + length;
byte[] tmp = new byte[capacity];
System.arraycopy (buffer, 0, tmp, 0, index);
|