Java 将 outputStream 转换为字节数组
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/43081008/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
converting outputStream to byte array
提问by henri Dunand
How can I get the bytes of an outputStream, or how can I convert an outputStream to a byte array?
如何获取 outputStream 的字节,或者如何将 outputStream 转换为字节数组?
采纳答案by PNS
From a theoretical perspective (i.e., irrespective of whether it makes sense in practice as a use case), this is an interesting question that essentially requires the implementation of a method like
从理论的角度来看(即,不管它作为用例在实践中是否有意义),这是一个有趣的问题,它本质上需要实现像
public abstract byte[] convert(OutputStream out);
The Java
OutputStream
class, as its name implies, only supports an overridden write()
method for I/O, and that write()
method gets either an integer (representing 1 byte) or a byte
array, the contents of which it sends to an output (e.g., a file).
的Java
OutputStream
类,正如其名称所暗示的,仅支持一个重写write()
为I / O方法,以及write()
方法获取一个整数(表示1个字节)或一个byte
阵列,其中将它发送到一个输出端(例如,一个文件)的内容。
For example, the following code saves the bytes already present in the data
array, to the output.txt
file:
例如,以下代码将data
数组中已存在的字节保存到output.txt
文件中:
byte[] data = ... // Get some data
OutputStream fos = new FileOutputStream("path/to/output.txt");
fos.write(data);
In order to get all the data that a given OutputStream
will be outputting and put it into a byte
array (i.e., into a byte[]
object), the class from which the corresponding OutputStream
object was instantiated, should keep storing all the bytes processed via its write()
methods and provide a special method, such as toByteArray()
, that would return them all, upon invocation.
为了获取给定OutputStream
将要输出的所有数据并将其放入byte
数组(即放入byte[]
对象)中,从中OutputStream
实例化相应对象的类应继续存储通过其write()
方法处理的所有字节并提供一个特殊方法,例如toByteArray()
,在调用时将全部返回。
This is exactly what the ByteArrayOutputStream
class does, making the convert()
method trivial (and unnecessary):
这正是ByteArrayOutputStream
该类所做的,使该convert()
方法变得微不足道(并且不必要):
public byte[] convert(ByteArrayOutputStream out) {
return out.toByteArray();
}
For any other type of OutputStream
, not inherently supporting a similar conversion to a byte[]
object, there is no way to make the conversion, before the OutputStream
is drained, i.e. before the desired calls to its write()
methods have been completed.
对于任何其他类型的OutputStream
,本身不支持到byte[]
对象的类似转换,在OutputStream
被耗尽之前,即在write()
完成对其方法的所需调用之前,无法进行转换。
If such an assumption (of the writes to have been completed) can be made, and if the original OutputStream
object can be replaced, then one option is to wrap it inside a delegate class that would essentially "grab" the bytes that would be supplied via its write()
methods. For example:
如果可以做出这样的假设(写入已经完成),并且如果原始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();
}
}
The calls to the write()
methods of the internal "buffer" (ByteArrayOutputStream
) precede the calls to the original stream (which, in turn, can be accessed via super
, or even via this.out
, since the corresponding parameter of the FilterOutputStream
is protected
). This makes sure that the bytes will be buffered, even if there is an exception while writing to the original stream.
到呼叫write()
内部的方法“缓冲”( ByteArrayOutputStream
)之前的原始流(这反过来,可以通过被访问的呼叫super
,或者甚至通过this.out
,由于的相应参数FilterOutputStream
是protected
)。这确保字节将被缓冲,即使在写入原始流时出现异常。
To reduce the overhead, the calls to super
in the above class can be omitted - e.g., if only the "conversion" to a byte
array is desired. Even the ByteArrayOutputStream
or OutputStream
classes can be used as parent classes, with a bit more work and some assumptions (e.g., about the reset()
method).
为了减少开销,super
可以省略上述类中的调用- 例如,如果只需要“转换”到byte
数组。甚至ByteArrayOutputStream
orOutputStream
类也可以用作父类,需要做更多的工作和一些假设(例如,关于reset()
方法)。
In any case, enough memory has to be available for the draining to take place and for the toByteArray()
method to work.
在任何情况下,都必须有足够的内存可供排空和toByteArray()
方法工作。
回答by Vadim
For @Obicere comment example:
对于@Obicere 评论示例:
ByteArrayOutputStream btOs = new ByteArrayOutputStream();
btOs.write("test bytes".getBytes());
String restoredString = new String(btOs.toByteArray());
System.out.println(restoredString);