2010-04-26 45 views
20

在Java中,我需要将OutputStream中的内容(我自己将数据填充到该流中)放入ByteBuffer中。如何以简单的方式做到这一点?如何将数据从OutputStream放入ByteBuffer?

+1

通常,您不能直接从输出流中读取数据。如果你自己填写数据,为什么你不能将它填充到ByteBuffer中呢? – 2010-04-26 20:28:17

+0

如果您创建继承了OutputStream形式的类并使其可以直接从中读取,则可以间接读取它以及直接读取原因。我没有自己填充数据,有的框架(以及我不想触及的框架代码)。请参阅我的其他评论和答案。 – drasto 2010-04-30 21:19:13

回答

30

您可以创建ByteArrayOutputStream并写入,并使用toByteArray()将内容解压缩为byte[]。然后ByteBuffer.wrap(byte [])将创建一个ByteBuffer与输出字节数组的内容。

+0

这正是我在阅读你的评论之前所做的。所以我可以批准这个工作:)) – drasto 2010-04-26 21:08:28

+5

不幸的是,'ByteArrayOutputStream#toByteArray()'产生了一个底层字节数组的副本,所以尽管这个方法很简单,但并不像我们想的那样高效。然而,由于“ByteBuffer”的容量是固定的,因此通过'OutputStream'将任意数量的数据写入'ByteBuffer'是不可调和的。 – seh 2012-02-02 00:37:21

+0

@seh它不一定要这样 - 看我的答案。 – mark 2013-03-28 16:05:36

1

尝试使用PipedOutputStream代替OutputStream。然后,您可以连接一个PipedInputStream以从PipedOutputStream中读取数据。

+0

看起来很好。 ByteArrayOutputStream通过调用它的newInputStream方法可以做类似的想法。然而,还有更直接的解决方案 - 将ByteArrayOutputStream直接备份到ByteBuffer的数组。这就是我所做的。 – drasto 2010-04-26 21:12:03

18

@ DJClayworth的答案是一个更有效的变体。

作为@seh正确地注意到,ByteArrayOutputStream.toByteArray()返回背衬byte[]对象,它可能是低效的拷贝。但是,支持byte[]对象以及字节数都是ByteArrayOutputStream类的受保护成员。因此,你可以创建自己的ByteArrayOutputStream的变种直接暴露他们:

public class MyByteArrayOutputStream extends ByteArrayOutputStream { 
    public MyByteArrayOutputStream() { 
    } 

    public MyByteArrayOutputStream(int size) { 
    super(size); 
    } 

    public int getCount() { 
    return count; 
    } 

    public byte[] getBuf() { 
    return buf; 
    } 
} 

使用这个类很简单:

MyByteArrayOutputStream out = new MyByteArrayOutputStream(); 
fillTheOutputStream(out); 
return new ByteArrayInputStream(out.getBuf(), 0, out.getCount()); 

其结果是,一旦所有的输出写入使用相同的缓冲作为输入流的基础。

+3

好点,@mark。我在几个Java项目中都有这样的类,通常被限制为一个名为'PromiscuousByteArrayOutputStream'的包 - 私有类。这个名字故意漫长而不祥。 – seh 2013-03-28 19:27:20

+1

getCount()不需要,因为ByteArrayOutputStream.size()返回count。 – 2014-12-24 02:30:37

4

尽管上面提到的答案可以解决您的问题,但它们都不像您期望的那样高效。 ByteArrayOutputStream或MyByteArrayOutputStream首先将数据写入Java堆内存,然后将其复制到ByteBuffer,这极大地影响了性能。

一个有效的实现是你自己写ByteBufferOutputStream类。其实这很容易做到。你必须提供一个write()方法。看到这个链接ByteBufferInputStream

+0

,因为我们可能需要为OutputStream重用现有的ByteBuffer(及其底层数组),而不是分配新数组来获得新的ByteBuffer,我相信这个答案更可接受。 – Ambling 2017-06-06 15:55:34