从理论角度来看(即,无论作为用例在实践中是否有意义),这是一个有趣的问题,本质上需要实现类似的方法
public abstract byte[] convert(OutputStream out);
The Java OutputStream https://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html类,顾名思义,只支持重写write()
I/O 方法,以及write()
方法获取一个整数(代表 1 个字节)或一个byte
数组,将其内容发送到输出(例如文件)。
例如,以下代码保存已存在于中的字节data
数组,到output.txt
file:
byte[] data = ... // Get some data
OutputStream fos = new FileOutputStream("path/to/output.txt");
fos.write(data);
为了获取给定的所有数据OutputStream
将输出并将其放入byte
数组(即,进入byte[]
object),对应的类OutputStream
对象被实例化,应该继续存储通过其处理的所有字节write()
方法并提供特殊方法,例如toByteArray()
,这将在调用时返回所有内容。
这正是ByteArrayOutputStream
类确实如此,使得convert()
方法很简单(而且不必要):
public byte[] convert(ByteArrayOutputStream out) {
return out.toByteArray();
}
对于任何其他类型OutputStream
,本质上并不支持类似的转换byte[]
对象,在之前没有办法进行转换OutputStream
被耗尽,即在对其进行所需的调用之前write()
方法已经完成。
如果可以做出这样的假设(写入已完成),并且如果原始OutputStream
对象可以被替换,那么一种选择是将其包装在委托类中,该委托类本质上“抓取”通过其提供的字节write()
方法。例如:
public class DrainableOutputStream extends FilterOutputStream {
private final ByteArrayOutputStream buffer;
public DrainableOutputStream(OutputStream out) {
super(out);
this.buffer = new ByteArrayOutputStream();
}
@Override
public void write(byte b[]) throws IOException {
this.buffer.write(b);
super.write(b);
}
@Override
public void write(byte b[], int off, int len) throws IOException {
this.buffer.write(b, off, len);
super.write(b, off, len);
}
@Override
public void write(int b) throws IOException {
this.buffer.write(b);
super.write(b);
}
public byte[] toByteArray() {
return this.buffer.toByteArray();
}
}
致电write()
内部“缓冲区”的方法(ByteArrayOutputStream
)先于对原始流的调用(反过来,可以通过super
,甚至通过this.out
,因为相应的参数FilterOutputStream
is protected
)。这可以确保字节被缓冲,即使在写入原始流时出现异常也是如此。
为了减少开销,调用super
上面的类中的可以省略 - 例如,如果仅“转换”为byte
需要数组。即便是ByteArrayOutputStream
or OutputStream
类可以用作父类,需要更多的工作和一些假设(例如,关于reset()
方法)。
无论如何,必须有足够的内存可用于进行排空和toByteArray()
工作方法。