22

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

4

7 回答 7

34

您可以创建 aByteArrayOutputStream并对其进行写入,然后将内容提取为byte[]using toByteArray()。然后ByteBuffer.wrap(byte [])将创建一个ByteBuffer包含输出字节数组的内容。

于 2010-04-26T21:02:45.553 回答
25

@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());

因此,一旦所有输出都被写入,同一个缓冲区就被用作输入流的基础。

于 2013-03-28T16:05:05.790 回答
6

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

一个有效的实现是自己编写 ByteBufferOutputStream 类。其实这很容易做到。您只需提供一个 write() 方法。请参阅此链接以获取ByteBufferInputStream

于 2014-05-09T17:39:19.080 回答
1

尝试使用 PipedOutputStream 而不是 OutputStream。然后,您可以连接 PipedInputStream 以从 PipedOutputStream 中读回数据。

于 2010-04-26T20:53:24.903 回答
1

你说你自己写这个流?如果是这样,也许您可​​以实现自己的 ByteBufferOutputStream 并即插即用。

基类看起来像这样:

public class ByteBufferOutputStream extends OutputStream {
    //protected WritableByteChannel wbc; //if you need to write directly to a channel
    protected static int bs = 2 * 1024 * 1024; //2MB buffer size, change as needed
    protected ByteBuffer bb = ByteBuffer.allocate(bs);

    public ByteBufferOutputStream(...) {
        //wbc = ... //again for writing to a channel
    }

    @Override
    public void write(int i) throws IOException {
        if (!bb.hasRemaining()) flush();
        byte b = (byte) i;
        bb.put(b);
    }

    @Override
    public void write(byte[] b, int off, int len) throws IOException {
        if (bb.remaining() < len) flush();
        bb.put(b, off, len);
    }

    /* do something with the buffer when it's full (perhaps write to channel?)
    @Override
    public void flush() throws IOException {
        bb.flip();
        wbc.write(bb);
        bb.clear();
    }

    @Override
    public void close() throws IOException {
        flush();
        wbc.close();
    }
    /*
}
于 2018-11-06T11:45:10.783 回答
1

//从扩展类访问受保护的成员buf & count

class ByteArrayOutputStream2ByteBuffer extends ByteArrayOutputStream {
    public ByteBuffer toByteBuffer() {
        return ByteBuffer.wrap(buf, 0, count);
    }
}
于 2020-03-30T06:59:16.073 回答
0

ByteBuffer查看支持OutputStream动态重新分配的有效实施。

/**
 * Wraps a {@link ByteBuffer} so it can be used like an {@link OutputStream}. This is similar to a
 * {@link java.io.ByteArrayOutputStream}, just that this uses a {@code ByteBuffer} instead of a
 * {@code byte[]} as internal storage.
 */
public class ByteBufferOutputStream extends OutputStream {

    private ByteBuffer wrappedBuffer;
    private final boolean autoEnlarge;

https://gist.github.com/hoijui/7fe8a6d31b20ae7af945

于 2022-01-29T18:39:09.333 回答